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) 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 return disk; 16 } 17 18 struct disk_image *disk_image__new_readonly(int fd, u64 size, struct disk_image_operations *ops) 19 { 20 struct disk_image *disk; 21 22 disk = disk_image__new(fd, size, ops); 23 if (!disk) 24 return NULL; 25 26 disk->priv = mmap(NULL, size, PROT_RW, MAP_PRIVATE | MAP_NORESERVE, fd, 0); 27 if (disk->priv == MAP_FAILED) 28 die("mmap() failed"); 29 return disk; 30 } 31 32 struct disk_image *disk_image__open(const char *filename, bool readonly) 33 { 34 struct disk_image *disk; 35 struct stat st; 36 int fd; 37 38 if (stat(filename, &st) < 0) 39 return NULL; 40 41 if (S_ISBLK(st.st_mode)) 42 return blkdev__probe(filename, &st); 43 44 fd = open(filename, readonly ? O_RDONLY : O_RDWR); 45 if (fd < 0) 46 return NULL; 47 48 disk = qcow_probe(fd, readonly); 49 if (disk) 50 return disk; 51 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 void 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; 67 68 if (disk->ops->close) 69 disk->ops->close(disk); 70 71 if (close(disk->fd) < 0) 72 warning("close() failed"); 73 74 free(disk); 75 } 76 77 /* Fill iov with disk data, starting from sector 'sector'. Return amount of bytes read. */ 78 ssize_t disk_image__read_sector_iov(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount) 79 { 80 u64 first_sector = sector; 81 82 if (disk->ops->read_sector_iov) 83 return disk->ops->read_sector_iov(disk, sector, iov, iovcount); 84 85 while (iovcount--) { 86 if (disk->ops->read_sector(disk, sector, iov->iov_base, iov->iov_len) < 0) 87 return -1; 88 89 sector += iov->iov_len >> SECTOR_SHIFT; 90 iov++; 91 } 92 93 return (sector - first_sector) << SECTOR_SHIFT; 94 } 95 96 /* Write iov to disk, starting from sector 'sector'. Return amount of bytes written. */ 97 ssize_t disk_image__write_sector_iov(struct disk_image *disk, u64 sector, const struct iovec *iov, int iovcount) 98 { 99 u64 first_sector = sector; 100 101 if (disk->ops->write_sector_iov) 102 return disk->ops->write_sector_iov(disk, sector, iov, iovcount); 103 104 while (iovcount--) { 105 if (disk->ops->write_sector(disk, sector, iov->iov_base, iov->iov_len) < 0) 106 return -1; 107 108 sector += iov->iov_len >> SECTOR_SHIFT; 109 iov++; 110 } 111 112 return (sector - first_sector) << SECTOR_SHIFT; 113 } 114