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 pr_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 pr_warning("close() failed"); 81 82 free(disk); 83 84 return 0; 85 } 86 87 /* 88 * Fill iov with disk data, starting from sector 'sector'. 89 * Return amount of bytes read. 90 */ 91 ssize_t disk_image__read(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount) 92 { 93 ssize_t total = 0; 94 ssize_t nr; 95 96 if (disk->ops->read_sector_iov) { 97 /* 98 * Try mulitple buffer based operation first 99 */ 100 total = disk->ops->read_sector_iov(disk, sector, iov, iovcount); 101 if (total < 0) { 102 pr_info("disk_image__read error: total=%ld\n", (long)total); 103 return -1; 104 } 105 } else if (disk->ops->read_sector) { 106 /* 107 * Fallback to single buffer based operation 108 */ 109 while (iovcount--) { 110 nr = disk->ops->read_sector(disk, sector, iov->iov_base, iov->iov_len); 111 if (nr != (ssize_t)iov->iov_len) { 112 pr_info("disk_image__read error: nr = %ld iov_len=%ld\n", (long)nr, (long)iov->iov_len); 113 return -1; 114 } 115 sector += iov->iov_len >> SECTOR_SHIFT; 116 iov++; 117 total += nr; 118 } 119 } else 120 die("No disk image operation for read\n"); 121 122 return total; 123 } 124 125 /* 126 * Write iov to disk, starting from sector 'sector'. 127 * Return amount of bytes written. 128 */ 129 ssize_t disk_image__write(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount) 130 { 131 ssize_t total = 0; 132 ssize_t nr; 133 134 if (disk->ops->write_sector_iov) { 135 /* 136 * Try writev based operation first 137 */ 138 total = disk->ops->write_sector_iov(disk, sector, iov, iovcount); 139 if (total < 0) { 140 pr_info("disk_image__write error: total=%ld\n", (long)total); 141 return -1; 142 } 143 } else if (disk->ops->write_sector) { 144 /* 145 * Fallback to single buffer based operation 146 */ 147 while (iovcount--) { 148 nr = disk->ops->write_sector(disk, sector, iov->iov_base, iov->iov_len); 149 if (nr != (ssize_t)iov->iov_len) { 150 pr_info("disk_image__write error: nr=%ld iov_len=%ld\n", (long)nr, (long)iov->iov_len); 151 return -1; 152 } 153 154 sector += iov->iov_len >> SECTOR_SHIFT; 155 iov++; 156 total += nr; 157 } 158 } else 159 die("No disk image operation for read\n"); 160 161 return total; 162 } 163