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