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 void disk_image__close_all(struct disk_image **disks, int count) 119 { 120 while (count) 121 disk_image__close(disks[--count]); 122 123 free(disks); 124 } 125 126 /* 127 * Fill iov with disk data, starting from sector 'sector'. 128 * Return amount of bytes read. 129 */ 130 ssize_t disk_image__read(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount) 131 { 132 ssize_t total = 0; 133 ssize_t nr; 134 135 if (disk->ops->read_sector_iov) { 136 /* 137 * Try mulitple buffer based operation first 138 */ 139 total = disk->ops->read_sector_iov(disk, sector, iov, iovcount); 140 if (total < 0) { 141 pr_info("disk_image__read error: total=%ld\n", (long)total); 142 return -1; 143 } 144 } else if (disk->ops->read_sector) { 145 /* 146 * Fallback to single buffer based operation 147 */ 148 while (iovcount--) { 149 nr = disk->ops->read_sector(disk, sector, iov->iov_base, iov->iov_len); 150 if (nr != (ssize_t)iov->iov_len) { 151 pr_info("disk_image__read error: nr = %ld iov_len=%ld\n", (long)nr, (long)iov->iov_len); 152 return -1; 153 } 154 sector += iov->iov_len >> SECTOR_SHIFT; 155 iov++; 156 total += nr; 157 } 158 } else 159 die("No disk image operation for read\n"); 160 161 return total; 162 } 163 164 /* 165 * Write iov to disk, starting from sector 'sector'. 166 * Return amount of bytes written. 167 */ 168 ssize_t disk_image__write(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount) 169 { 170 ssize_t total = 0; 171 ssize_t nr; 172 173 if (disk->ops->write_sector_iov) { 174 /* 175 * Try writev based operation first 176 */ 177 total = disk->ops->write_sector_iov(disk, sector, iov, iovcount); 178 if (total < 0) { 179 pr_info("disk_image__write error: total=%ld\n", (long)total); 180 return -1; 181 } 182 } else if (disk->ops->write_sector) { 183 /* 184 * Fallback to single buffer based operation 185 */ 186 while (iovcount--) { 187 nr = disk->ops->write_sector(disk, sector, iov->iov_base, iov->iov_len); 188 if (nr != (ssize_t)iov->iov_len) { 189 pr_info("disk_image__write error: nr=%ld iov_len=%ld\n", (long)nr, (long)iov->iov_len); 190 return -1; 191 } 192 193 sector += iov->iov_len >> SECTOR_SHIFT; 194 iov++; 195 total += nr; 196 } 197 } else 198 die("No disk image operation for read\n"); 199 200 return total; 201 } 202