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