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 } 194