1 #include "kvm/disk-image.h" 2 #include "kvm/qcow.h" 3 4 struct disk_image *disk_image__new(int fd, u64 size, struct disk_image_operations *ops, int use_mmap) 5 { 6 struct disk_image *disk; 7 8 disk = malloc(sizeof *disk); 9 if (!disk) 10 return NULL; 11 12 disk->fd = fd; 13 disk->size = size; 14 disk->ops = ops; 15 16 if (use_mmap == DISK_IMAGE_MMAP) { 17 /* 18 * The write to disk image will be discarded 19 */ 20 disk->priv = mmap(NULL, size, PROT_RW, MAP_PRIVATE | MAP_NORESERVE, fd, 0); 21 if (disk->priv == MAP_FAILED) 22 die("mmap() failed"); 23 } 24 25 return disk; 26 } 27 28 struct disk_image *disk_image__open(const char *filename, bool readonly) 29 { 30 struct disk_image *disk; 31 struct stat st; 32 int fd; 33 34 if (stat(filename, &st) < 0) 35 return NULL; 36 37 /* blk device ?*/ 38 disk = blkdev__probe(filename, &st); 39 if (disk) 40 return disk; 41 42 fd = open(filename, readonly ? O_RDONLY : O_RDWR); 43 if (fd < 0) 44 return NULL; 45 46 /* qcow image ?*/ 47 disk = qcow_probe(fd, readonly); 48 if (disk) 49 return disk; 50 51 /* raw image ?*/ 52 disk = raw_image__probe(fd, &st, readonly); 53 if (disk) 54 return disk; 55 56 if (close(fd) < 0) 57 warning("close() failed"); 58 59 return NULL; 60 } 61 62 int disk_image__close(struct disk_image *disk) 63 { 64 /* If there was no disk image then there's nothing to do: */ 65 if (!disk) 66 return 0; 67 68 if (disk->ops->close) 69 return disk->ops->close(disk); 70 71 if (close(disk->fd) < 0) 72 warning("close() failed"); 73 74 free(disk); 75 76 return 0; 77 } 78 79 /* Fill iov with disk data, starting from sector 'sector'. Return amount of bytes read. */ 80 ssize_t disk_image__read(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount) 81 { 82 u64 first_sector = sector; 83 84 if (disk->ops->read_sector_iov) 85 return disk->ops->read_sector_iov(disk, sector, iov, iovcount); 86 87 while (iovcount--) { 88 if (disk->ops->read_sector(disk, sector, iov->iov_base, iov->iov_len) < 0) 89 return -1; 90 91 sector += iov->iov_len >> SECTOR_SHIFT; 92 iov++; 93 } 94 95 return (sector - first_sector) << SECTOR_SHIFT; 96 } 97 98 /* Write iov to disk, starting from sector 'sector'. Return amount of bytes written. */ 99 ssize_t disk_image__write(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount) 100 { 101 u64 first_sector = sector; 102 103 if (disk->ops->write_sector_iov) 104 return disk->ops->write_sector_iov(disk, sector, iov, iovcount); 105 106 while (iovcount--) { 107 if (disk->ops->write_sector(disk, sector, iov->iov_base, iov->iov_len) < 0) 108 return -1; 109 110 sector += iov->iov_len >> SECTOR_SHIFT; 111 iov++; 112 } 113 114 return (sector - first_sector) << SECTOR_SHIFT; 115 } 116