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