]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - tools/kvm/disk/core.c
37ae5c921e2191a68669bc00b3086d9d7a3a6ce6
[karo-tx-linux.git] / tools / kvm / disk / core.c
1 #include "kvm/disk-image.h"
2 #include "kvm/qcow.h"
3
4 struct disk_image *disk_image__new(int fd, u64 size, struct disk_image_operations *ops, int use_mmap)
5 {
6         struct disk_image *disk;
7
8         disk            = malloc(sizeof *disk);
9         if (!disk)
10                 return NULL;
11
12         disk->fd        = fd;
13         disk->size      = size;
14         disk->ops       = ops;
15
16         if (use_mmap == DISK_IMAGE_MMAP) {
17                 /*
18                  * The write to disk image will be discarded
19                  */
20                 disk->priv = mmap(NULL, size, PROT_RW, MAP_PRIVATE | MAP_NORESERVE, fd, 0);
21                 if (disk->priv == MAP_FAILED)
22                         die("mmap() failed");
23         }
24
25         return disk;
26 }
27
28 struct disk_image *disk_image__open(const char *filename, bool readonly)
29 {
30         struct disk_image *disk;
31         struct stat st;
32         int fd;
33
34         if (stat(filename, &st) < 0)
35                 return NULL;
36
37         /* blk device ?*/
38         disk            = blkdev__probe(filename, &st);
39         if (disk)
40                 return disk;
41
42         fd              = open(filename, readonly ? O_RDONLY : O_RDWR);
43         if (fd < 0)
44                 return NULL;
45
46         /* qcow image ?*/
47         disk            = qcow_probe(fd, readonly);
48         if (disk)
49                 return disk;
50
51         /* raw image ?*/
52         disk            = raw_image__probe(fd, &st, readonly);
53         if (disk)
54                 return disk;
55
56         if (close(fd) < 0)
57                 pr_warning("close() failed");
58
59         return NULL;
60 }
61
62 struct disk_image **disk_image__open_all(const char **filenames, bool *readonly, int count)
63 {
64         struct disk_image **disks;
65         int i;
66
67         if (!count || count > MAX_DISK_IMAGES)
68                 return NULL;
69
70         disks = calloc(count, sizeof(*disks));
71         if (!disks)
72                 return NULL;
73
74         for (i = 0; i < count; i++) {
75                 if (!filenames[i])
76                         continue;
77
78                 disks[i] = disk_image__open(filenames[i], readonly[i]);
79                 if (!disks[i]) {
80                         pr_error("Loading disk image '%s' failed", filenames[i]);
81                         goto error;
82                 }
83         }
84         return disks;
85 error:
86         for (i = 0; i < count; i++)
87                 disk_image__close(disks[i]);
88
89         free(disks);
90         return NULL;
91 }
92
93 int disk_image__flush(struct disk_image *disk)
94 {
95         if (disk->ops->flush)
96                 return disk->ops->flush(disk);
97
98         return fsync(disk->fd);
99 }
100
101 int disk_image__close(struct disk_image *disk)
102 {
103         /* If there was no disk image then there's nothing to do: */
104         if (!disk)
105                 return 0;
106
107         if (disk->ops->close)
108                 return disk->ops->close(disk);
109
110         if (close(disk->fd) < 0)
111                 pr_warning("close() failed");
112
113         free(disk);
114
115         return 0;
116 }
117
118 /*
119  * Fill iov with disk data, starting from sector 'sector'.
120  * Return amount of bytes read.
121  */
122 ssize_t disk_image__read(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount)
123 {
124         ssize_t total = 0;
125         ssize_t nr;
126
127         if (disk->ops->read_sector_iov) {
128                 /*
129                  * Try mulitple buffer based operation first
130                  */
131                 total           = disk->ops->read_sector_iov(disk, sector, iov, iovcount);
132                 if (total < 0) {
133                         pr_info("disk_image__read error: total=%ld\n", (long)total);
134                         return -1;
135                 }
136         } else if (disk->ops->read_sector) {
137                 /*
138                  * Fallback to single buffer based operation
139                  */
140                 while (iovcount--) {
141                         nr      = disk->ops->read_sector(disk, sector, iov->iov_base, iov->iov_len);
142                         if (nr != (ssize_t)iov->iov_len) {
143                                 pr_info("disk_image__read error: nr = %ld iov_len=%ld\n", (long)nr, (long)iov->iov_len);
144                                 return -1;
145                         }
146                         sector  += iov->iov_len >> SECTOR_SHIFT;
147                         iov++;
148                         total   += nr;
149                 }
150         } else
151                 die("No disk image operation for read\n");
152
153         return total;
154 }
155
156 /*
157  * Write iov to disk, starting from sector 'sector'.
158  * Return amount of bytes written.
159  */
160 ssize_t disk_image__write(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount)
161 {
162         ssize_t total = 0;
163         ssize_t nr;
164
165         if (disk->ops->write_sector_iov) {
166                 /*
167                  * Try writev based operation first
168                  */
169                 total = disk->ops->write_sector_iov(disk, sector, iov, iovcount);
170                 if (total < 0) {
171                         pr_info("disk_image__write error: total=%ld\n", (long)total);
172                         return -1;
173                 }
174         } else if (disk->ops->write_sector) {
175                 /*
176                  * Fallback to single buffer based operation
177                  */
178                 while (iovcount--) {
179                         nr       = disk->ops->write_sector(disk, sector, iov->iov_base, iov->iov_len);
180                         if (nr != (ssize_t)iov->iov_len) {
181                                 pr_info("disk_image__write error: nr=%ld iov_len=%ld\n", (long)nr, (long)iov->iov_len);
182                                 return -1;
183                         }
184
185                         sector  += iov->iov_len >> SECTOR_SHIFT;
186                         iov++;
187                         total   += nr;
188                 }
189         } else
190                 die("No disk image operation for read\n");
191
192         return total;
193 }