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 bool readonly; 126 bool direct; 127 void *err; 128 int i; 129 130 if (!count) 131 return ERR_PTR(-EINVAL); 132 if (count > MAX_DISK_IMAGES) 133 return ERR_PTR(-ENOSPC); 134 135 disks = calloc(count, sizeof(*disks)); 136 if (!disks) 137 return ERR_PTR(-ENOMEM); 138 139 for (i = 0; i < count; i++) { 140 filename = params[i].filename; 141 readonly = params[i].readonly; 142 direct = params[i].direct; 143 if (!filename) 144 continue; 145 146 disks[i] = disk_image__open(filename, readonly, direct); 147 if (IS_ERR_OR_NULL(disks[i])) { 148 pr_err("Loading disk image '%s' failed", filename); 149 err = disks[i]; 150 goto error; 151 } 152 } 153 154 return disks; 155 error: 156 for (i = 0; i < count; i++) 157 if (!IS_ERR_OR_NULL(disks[i])) 158 disk_image__close(disks[i]); 159 160 free(disks); 161 return err; 162 } 163 164 int disk_image__flush(struct disk_image *disk) 165 { 166 if (disk->ops->flush) 167 return disk->ops->flush(disk); 168 169 return fsync(disk->fd); 170 } 171 172 int disk_image__close(struct disk_image *disk) 173 { 174 /* If there was no disk image then there's nothing to do: */ 175 if (!disk) 176 return 0; 177 178 if (disk->ops->close) 179 return disk->ops->close(disk); 180 181 if (close(disk->fd) < 0) 182 pr_warning("close() failed"); 183 184 free(disk); 185 186 return 0; 187 } 188 189 int disk_image__close_all(struct disk_image **disks, int count) 190 { 191 while (count) 192 disk_image__close(disks[--count]); 193 194 free(disks); 195 196 return 0; 197 } 198 199 /* 200 * Fill iov with disk data, starting from sector 'sector'. 201 * Return amount of bytes read. 202 */ 203 ssize_t disk_image__read(struct disk_image *disk, u64 sector, 204 const struct iovec *iov, int iovcount, void *param) 205 { 206 ssize_t total = 0; 207 208 if (debug_iodelay) 209 msleep(debug_iodelay); 210 211 if (disk->ops->read) { 212 total = disk->ops->read(disk, sector, iov, iovcount, param); 213 if (total < 0) { 214 pr_info("disk_image__read error: total=%ld\n", (long)total); 215 return total; 216 } 217 } 218 219 if (!disk->async && disk->disk_req_cb) 220 disk->disk_req_cb(param, total); 221 222 return total; 223 } 224 225 /* 226 * Write iov to disk, starting from sector 'sector'. 227 * Return amount of bytes written. 228 */ 229 ssize_t disk_image__write(struct disk_image *disk, u64 sector, 230 const struct iovec *iov, int iovcount, void *param) 231 { 232 ssize_t total = 0; 233 234 if (debug_iodelay) 235 msleep(debug_iodelay); 236 237 if (disk->ops->write) { 238 /* 239 * Try writev based operation first 240 */ 241 242 total = disk->ops->write(disk, sector, iov, iovcount, param); 243 if (total < 0) { 244 pr_info("disk_image__write error: total=%ld\n", (long)total); 245 return total; 246 } 247 } else { 248 /* Do nothing */ 249 } 250 251 if (!disk->async && disk->disk_req_cb) 252 disk->disk_req_cb(param, total); 253 254 return total; 255 } 256 257 ssize_t disk_image__get_serial(struct disk_image *disk, void *buffer, ssize_t *len) 258 { 259 struct stat st; 260 int r; 261 262 r = fstat(disk->fd, &st); 263 if (r) 264 return r; 265 266 *len = snprintf(buffer, *len, "%llu%llu%llu", 267 (u64)st.st_dev, (u64)st.st_rdev, (u64)st.st_ino); 268 return *len; 269 } 270 271 void disk_image__set_callback(struct disk_image *disk, 272 void (*disk_req_cb)(void *param, long len)) 273 { 274 disk->disk_req_cb = disk_req_cb; 275 } 276