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