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