Add linux-next specific files for 20110831
[linux-2.6/next.git] / tools / kvm / disk / core.c
blob20e19900c00dca7374f26e899b2c60c4f199808c
1 #include "kvm/disk-image.h"
2 #include "kvm/qcow.h"
4 int debug_iodelay;
6 struct disk_image *disk_image__new(int fd, u64 size, struct disk_image_operations *ops, int use_mmap)
8 struct disk_image *disk;
10 disk = malloc(sizeof *disk);
11 if (!disk)
12 return NULL;
14 disk->fd = fd;
15 disk->size = size;
16 disk->ops = ops;
18 if (use_mmap == DISK_IMAGE_MMAP) {
20 * The write to disk image will be discarded
22 disk->priv = mmap(NULL, size, PROT_RW, MAP_PRIVATE | MAP_NORESERVE, fd, 0);
23 if (disk->priv == MAP_FAILED)
24 die("mmap() failed");
27 return disk;
30 struct disk_image *disk_image__open(const char *filename, bool readonly)
32 struct disk_image *disk;
33 struct stat st;
34 int fd;
36 if (stat(filename, &st) < 0)
37 return NULL;
39 /* blk device ?*/
40 disk = blkdev__probe(filename, &st);
41 if (disk)
42 return disk;
44 fd = open(filename, readonly ? O_RDONLY : O_RDWR);
45 if (fd < 0)
46 return NULL;
48 /* qcow image ?*/
49 disk = qcow_probe(fd, true);
50 if (disk) {
51 pr_warning("Forcing read-only support for QCOW");
52 return disk;
55 /* raw image ?*/
56 disk = raw_image__probe(fd, &st, readonly);
57 if (disk)
58 return disk;
60 if (close(fd) < 0)
61 pr_warning("close() failed");
63 return NULL;
66 struct disk_image **disk_image__open_all(const char **filenames, bool *readonly, int count)
68 struct disk_image **disks;
69 int i;
71 if (!count || count > MAX_DISK_IMAGES)
72 return NULL;
74 disks = calloc(count, sizeof(*disks));
75 if (!disks)
76 return NULL;
78 for (i = 0; i < count; i++) {
79 if (!filenames[i])
80 continue;
82 disks[i] = disk_image__open(filenames[i], readonly[i]);
83 if (!disks[i]) {
84 pr_error("Loading disk image '%s' failed", filenames[i]);
85 goto error;
88 return disks;
89 error:
90 for (i = 0; i < count; i++)
91 disk_image__close(disks[i]);
93 free(disks);
94 return NULL;
97 int disk_image__flush(struct disk_image *disk)
99 if (disk->ops->flush)
100 return disk->ops->flush(disk);
102 return fsync(disk->fd);
105 int disk_image__close(struct disk_image *disk)
107 /* If there was no disk image then there's nothing to do: */
108 if (!disk)
109 return 0;
111 if (disk->ops->close)
112 return disk->ops->close(disk);
114 if (close(disk->fd) < 0)
115 pr_warning("close() failed");
117 free(disk);
119 return 0;
122 void disk_image__close_all(struct disk_image **disks, int count)
124 while (count)
125 disk_image__close(disks[--count]);
127 free(disks);
131 * Fill iov with disk data, starting from sector 'sector'.
132 * Return amount of bytes read.
134 ssize_t disk_image__read(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount)
136 ssize_t total = 0;
137 ssize_t nr;
139 if (debug_iodelay)
140 msleep(debug_iodelay);
142 if (disk->ops->read_sector_iov) {
144 * Try mulitple buffer based operation first
146 total = disk->ops->read_sector_iov(disk, sector, iov, iovcount);
147 if (total < 0) {
148 pr_info("disk_image__read error: total=%ld\n", (long)total);
149 return -1;
151 } else if (disk->ops->read_sector) {
153 * Fallback to single buffer based operation
155 while (iovcount--) {
156 nr = disk->ops->read_sector(disk, sector, iov->iov_base, iov->iov_len);
157 if (nr != (ssize_t)iov->iov_len) {
158 pr_info("disk_image__read error: nr = %ld iov_len=%ld\n", (long)nr, (long)iov->iov_len);
159 return -1;
161 sector += iov->iov_len >> SECTOR_SHIFT;
162 iov++;
163 total += nr;
165 } else
166 die("No disk image operation for read\n");
168 return total;
172 * Write iov to disk, starting from sector 'sector'.
173 * Return amount of bytes written.
175 ssize_t disk_image__write(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount)
177 ssize_t total = 0;
178 ssize_t nr;
180 if (debug_iodelay)
181 msleep(debug_iodelay);
183 if (disk->ops->write_sector_iov) {
185 * Try writev based operation first
187 total = disk->ops->write_sector_iov(disk, sector, iov, iovcount);
188 if (total < 0) {
189 pr_info("disk_image__write error: total=%ld\n", (long)total);
190 return -1;
192 } else if (disk->ops->write_sector) {
194 * Fallback to single buffer based operation
196 while (iovcount--) {
197 nr = disk->ops->write_sector(disk, sector, iov->iov_base, iov->iov_len);
198 if (nr != (ssize_t)iov->iov_len) {
199 pr_info("disk_image__write error: nr=%ld iov_len=%ld\n", (long)nr, (long)iov->iov_len);
200 return -1;
203 sector += iov->iov_len >> SECTOR_SHIFT;
204 iov++;
205 total += nr;
207 } else
208 die("No disk image operation for read\n");
210 return total;
213 ssize_t disk_image__get_serial(struct disk_image *disk, void *buffer, ssize_t *len)
215 struct stat st;
217 if (fstat(disk->fd, &st) != 0)
218 return 0;
220 *len = snprintf(buffer, *len, "%llu%llu%llu", (u64)st.st_dev, (u64)st.st_rdev, (u64)st.st_ino);
221 return *len;