19f532d00SPekka Enberg #include "kvm/disk-image.h" 286835cedSPrasad Joshi #include "kvm/qcow.h" 39f532d00SPekka Enberg 4aa400b00SPrasad Joshi int debug_iodelay; 5aa400b00SPrasad Joshi 67d22135fSAsias He struct disk_image *disk_image__new(int fd, u64 size, struct disk_image_operations *ops, int use_mmap) 79f532d00SPekka Enberg { 843835ac9SSasha Levin struct disk_image *disk; 99f532d00SPekka Enberg 1043835ac9SSasha Levin disk = malloc(sizeof *disk); 1143835ac9SSasha Levin if (!disk) 12fffb37a9SPekka Enberg return NULL; 139f532d00SPekka Enberg 1443835ac9SSasha Levin disk->fd = fd; 1543835ac9SSasha Levin disk->size = size; 1643835ac9SSasha Levin disk->ops = ops; 17f4ff38dfSPrasad Joshi 187d22135fSAsias He if (use_mmap == DISK_IMAGE_MMAP) { 197d22135fSAsias He /* 207d22135fSAsias He * The write to disk image will be discarded 217d22135fSAsias He */ 2237c34ca8SSasha Levin disk->priv = mmap(NULL, size, PROT_RW, MAP_PRIVATE | MAP_NORESERVE, fd, 0); 2343835ac9SSasha Levin if (disk->priv == MAP_FAILED) 249ac38fe1SSasha Levin die("mmap() failed"); 257d22135fSAsias He } 267d22135fSAsias He 2743835ac9SSasha Levin return disk; 289f532d00SPekka Enberg } 299f532d00SPekka Enberg 309ac38fe1SSasha Levin struct disk_image *disk_image__open(const char *filename, bool readonly) 31499f3bedSPekka Enberg { 3243835ac9SSasha Levin struct disk_image *disk; 336ec60cfdSPekka Enberg struct stat st; 34499f3bedSPekka Enberg int fd; 35499f3bedSPekka Enberg 366ec60cfdSPekka Enberg if (stat(filename, &st) < 0) 376ec60cfdSPekka Enberg return NULL; 386ec60cfdSPekka Enberg 39441767feSAsias He /* blk device ?*/ 40441767feSAsias He disk = blkdev__probe(filename, &st); 41441767feSAsias He if (disk) 42441767feSAsias He return disk; 436ec60cfdSPekka Enberg 449ac38fe1SSasha Levin fd = open(filename, readonly ? O_RDONLY : O_RDWR); 45499f3bedSPekka Enberg if (fd < 0) 46499f3bedSPekka Enberg return NULL; 47499f3bedSPekka Enberg 48441767feSAsias He /* qcow image ?*/ 4917f68274SPekka Enberg disk = qcow_probe(fd, true); 5017f68274SPekka Enberg if (disk) { 5117f68274SPekka Enberg pr_warning("Forcing read-only support for QCOW"); 5243835ac9SSasha Levin return disk; 5317f68274SPekka Enberg } 5486835cedSPrasad Joshi 55441767feSAsias He /* raw image ?*/ 5643835ac9SSasha Levin disk = raw_image__probe(fd, &st, readonly); 5743835ac9SSasha Levin if (disk) 5843835ac9SSasha Levin return disk; 59499f3bedSPekka Enberg 60d6c58e5bSPrasad Joshi if (close(fd) < 0) 614542f276SCyrill Gorcunov pr_warning("close() failed"); 62499f3bedSPekka Enberg 63499f3bedSPekka Enberg return NULL; 64499f3bedSPekka Enberg } 65499f3bedSPekka Enberg 66c1ed214eSPrasad Joshi struct disk_image **disk_image__open_all(const char **filenames, bool *readonly, int count) 67c1ed214eSPrasad Joshi { 68c1ed214eSPrasad Joshi struct disk_image **disks; 69c1ed214eSPrasad Joshi int i; 70c1ed214eSPrasad Joshi 71c1ed214eSPrasad Joshi if (!count || count > MAX_DISK_IMAGES) 72c1ed214eSPrasad Joshi return NULL; 73c1ed214eSPrasad Joshi 74c1ed214eSPrasad Joshi disks = calloc(count, sizeof(*disks)); 75c1ed214eSPrasad Joshi if (!disks) 76c1ed214eSPrasad Joshi return NULL; 77c1ed214eSPrasad Joshi 78c1ed214eSPrasad Joshi for (i = 0; i < count; i++) { 79c1ed214eSPrasad Joshi if (!filenames[i]) 80c1ed214eSPrasad Joshi continue; 81c1ed214eSPrasad Joshi 82c1ed214eSPrasad Joshi disks[i] = disk_image__open(filenames[i], readonly[i]); 83c1ed214eSPrasad Joshi if (!disks[i]) { 84c1ed214eSPrasad Joshi pr_error("Loading disk image '%s' failed", filenames[i]); 85c1ed214eSPrasad Joshi goto error; 86c1ed214eSPrasad Joshi } 87c1ed214eSPrasad Joshi } 88c1ed214eSPrasad Joshi return disks; 89c1ed214eSPrasad Joshi error: 90c1ed214eSPrasad Joshi for (i = 0; i < count; i++) 91c1ed214eSPrasad Joshi disk_image__close(disks[i]); 92c1ed214eSPrasad Joshi 93c1ed214eSPrasad Joshi free(disks); 94c1ed214eSPrasad Joshi return NULL; 95c1ed214eSPrasad Joshi } 96c1ed214eSPrasad Joshi 97fda63751SAsias He int disk_image__flush(struct disk_image *disk) 98fda63751SAsias He { 99fda63751SAsias He if (disk->ops->flush) 100fda63751SAsias He return disk->ops->flush(disk); 101fda63751SAsias He 102fda63751SAsias He return fsync(disk->fd); 103fda63751SAsias He } 104fda63751SAsias He 10572133dd2SAsias He int disk_image__close(struct disk_image *disk) 106499f3bedSPekka Enberg { 10782d94c50SIngo Molnar /* If there was no disk image then there's nothing to do: */ 10843835ac9SSasha Levin if (!disk) 10972133dd2SAsias He return 0; 11082d94c50SIngo Molnar 11143835ac9SSasha Levin if (disk->ops->close) 11272133dd2SAsias He return disk->ops->close(disk); 113499f3bedSPekka Enberg 11443835ac9SSasha Levin if (close(disk->fd) < 0) 1154542f276SCyrill Gorcunov pr_warning("close() failed"); 116499f3bedSPekka Enberg 11743835ac9SSasha Levin free(disk); 11872133dd2SAsias He 11972133dd2SAsias He return 0; 120499f3bedSPekka Enberg } 12170b0d7b0SSasha Levin 1229df47d00SPrasad Joshi void disk_image__close_all(struct disk_image **disks, int count) 1239df47d00SPrasad Joshi { 1249df47d00SPrasad Joshi while (count) 1259df47d00SPrasad Joshi disk_image__close(disks[--count]); 1269df47d00SPrasad Joshi 1279df47d00SPrasad Joshi free(disks); 1289df47d00SPrasad Joshi } 1299df47d00SPrasad Joshi 13097a90170SAsias He /* 13197a90170SAsias He * Fill iov with disk data, starting from sector 'sector'. 13297a90170SAsias He * Return amount of bytes read. 13397a90170SAsias He */ 134b8861977SAsias He ssize_t disk_image__read(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount) 13570b0d7b0SSasha Levin { 13697a90170SAsias He ssize_t total = 0; 13770b0d7b0SSasha Levin 138aa400b00SPrasad Joshi if (debug_iodelay) 139aa400b00SPrasad Joshi msleep(debug_iodelay); 140aa400b00SPrasad Joshi 141*2534c9b6SSasha Levin if (disk->ops->read_sector) { 142*2534c9b6SSasha Levin total = disk->ops->read_sector(disk, sector, iov, iovcount); 14397a90170SAsias He if (total < 0) { 1444542f276SCyrill Gorcunov pr_info("disk_image__read error: total=%ld\n", (long)total); 14570b0d7b0SSasha Levin return -1; 14697a90170SAsias He } 147*2534c9b6SSasha Levin } else { 14897a90170SAsias He die("No disk image operation for read\n"); 149*2534c9b6SSasha Levin } 15097a90170SAsias He 15197a90170SAsias He return total; 15270b0d7b0SSasha Levin } 15370b0d7b0SSasha Levin 15497a90170SAsias He /* 15597a90170SAsias He * Write iov to disk, starting from sector 'sector'. 15697a90170SAsias He * Return amount of bytes written. 15797a90170SAsias He */ 158b8861977SAsias He ssize_t disk_image__write(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount) 15970b0d7b0SSasha Levin { 16097a90170SAsias He ssize_t total = 0; 16170b0d7b0SSasha Levin 162aa400b00SPrasad Joshi if (debug_iodelay) 163aa400b00SPrasad Joshi msleep(debug_iodelay); 164aa400b00SPrasad Joshi 165*2534c9b6SSasha Levin if (disk->ops->write_sector) { 16697a90170SAsias He /* 16797a90170SAsias He * Try writev based operation first 16897a90170SAsias He */ 169*2534c9b6SSasha Levin total = disk->ops->write_sector(disk, sector, iov, iovcount); 17097a90170SAsias He if (total < 0) { 1714542f276SCyrill Gorcunov pr_info("disk_image__write error: total=%ld\n", (long)total); 17270b0d7b0SSasha Levin return -1; 17397a90170SAsias He } 174*2534c9b6SSasha Levin } else { 17597a90170SAsias He die("No disk image operation for read\n"); 176*2534c9b6SSasha Levin } 17770b0d7b0SSasha Levin 17897a90170SAsias He return total; 17970b0d7b0SSasha Levin } 180ff6462e8SSasha Levin 181ff6462e8SSasha Levin ssize_t disk_image__get_serial(struct disk_image *disk, void *buffer, ssize_t *len) 182ff6462e8SSasha Levin { 183ff6462e8SSasha Levin struct stat st; 184ff6462e8SSasha Levin 185ff6462e8SSasha Levin if (fstat(disk->fd, &st) != 0) 186ff6462e8SSasha Levin return 0; 187ff6462e8SSasha Levin 188eab301d0SSasha Levin *len = snprintf(buffer, *len, "%llu%llu%llu", (u64)st.st_dev, (u64)st.st_rdev, (u64)st.st_ino); 189ff6462e8SSasha Levin return *len; 190ff6462e8SSasha Levin } 191