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__flush(struct disk_image *disk) 63 { 64 if (disk->ops->flush) 65 return disk->ops->flush(disk); 66 67 return fsync(disk->fd); 68 } 69 70 int disk_image__close(struct disk_image *disk) 71 { 72 /* If there was no disk image then there's nothing to do: */ 73 if (!disk) 74 return 0; 75 76 if (disk->ops->close) 77 return disk->ops->close(disk); 78 79 if (close(disk->fd) < 0) 80 warning("close() failed"); 81 82 free(disk); 83 84 return 0; 85 } 86 87 /* Fill iov with disk data, starting from sector 'sector'. Return amount of bytes read. */ 88 ssize_t disk_image__read(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount) 89 { 90 u64 first_sector = sector; 91 92 if (disk->ops->read_sector_iov) 93 return disk->ops->read_sector_iov(disk, sector, iov, iovcount); 94 95 while (iovcount--) { 96 if (disk->ops->read_sector(disk, sector, iov->iov_base, iov->iov_len) < 0) 97 return -1; 98 99 sector += iov->iov_len >> SECTOR_SHIFT; 100 iov++; 101 } 102 103 return (sector - first_sector) << SECTOR_SHIFT; 104 } 105 106 /* Write iov to disk, starting from sector 'sector'. Return amount of bytes written. */ 107 ssize_t disk_image__write(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount) 108 { 109 u64 first_sector = sector; 110 111 if (disk->ops->write_sector_iov) 112 return disk->ops->write_sector_iov(disk, sector, iov, iovcount); 113 114 while (iovcount--) { 115 if (disk->ops->write_sector(disk, sector, iov->iov_base, iov->iov_len) < 0) 116 return -1; 117 118 sector += iov->iov_len >> SECTOR_SHIFT; 119 iov++; 120 } 121 122 return (sector - first_sector) << SECTOR_SHIFT; 123 } 124