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