Signed-off-by: Paolo Bonzini <pbonz...@redhat.com> --- block/raw-posix.c | 65 ++++++++++++++++++++++++++++++++++++++++++---------- block/raw-win32.c | 45 ++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 13 deletions(-)
diff --git a/block/raw-posix.c b/block/raw-posix.c index 3482fc8..f6747ad 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -279,22 +279,56 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags) return raw_open_common(bs, filename, flags, 0); } -/* XXX: use host sector size if necessary with: +static int raw_get_alignment(BlockDriverState *bs) +{ + BDRVRawState *s = bs->opaque; + unsigned int sector_size; + int ret; + + ret = fd_open(bs); + if (ret < 0) { + return ret; + } + + /* For block devices, try to get the actual sector size even if we + * do not need it, so that it can be passed down to the guest. + */ +#ifdef BLKSSZGET + if (ioctl(s->fd, BLKSSZGET, §or_size)) { + return sector size; + } +#endif +#ifdef DKIOCGETBLOCKSIZE + if (ioctl(s->fd, DKIOCGETBLOCKSIZE, §or_size)) { + return sector_size; + } +#endif #ifdef DIOCGSECTORSIZE - { - unsigned int sectorsize = 512; - if (!ioctl(fd, DIOCGSECTORSIZE, §orsize) && - sectorsize > bufsize) - bufsize = sectorsize; - } + if (ioctl(s->fd, DIOCGSECTORSIZE, §or_size)) { + return sector_size; + } #endif -#ifdef CONFIG_COCOA - uint32_t blockSize = 512; - if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) { - bufsize = blockSize; + + /* If we could not get the size so far, we can only guess it if + * the file was opened with O_DIRECT. If not, just return the + * minimal size. + * + * For /dev/sg devices the alignment is not really used, so return + * a dummy value for them too. + */ + if (bs->sg || !s->aligned_buf) { + return 512; + } + + for (sector_size = 512; sector_size < MAX_BLOCKSIZE; sector_size <<= 1) { + /* The buffer must be aligned to sector_size, but not sector_size*2. */ + if (pread(s->fd, s->aligned_buf + sector_size, sector_size, 0) >= 0) { + break; } -#endif -*/ + } + return sector_size; +} + /* * Check if all memory in this vector is sector aligned. @@ -642,6 +676,7 @@ static BlockDriver bdrv_file = { .bdrv_truncate = raw_truncate, .bdrv_getlength = raw_getlength, + .bdrv_get_alignment = raw_get_alignment, .bdrv_get_allocated_file_size = raw_get_allocated_file_size, @@ -910,6 +945,7 @@ static BlockDriver bdrv_host_device = { .bdrv_truncate = raw_truncate, .bdrv_getlength = raw_getlength, + .bdrv_get_alignment = raw_get_alignment, .bdrv_get_allocated_file_size = raw_get_allocated_file_size, @@ -1029,6 +1065,7 @@ static BlockDriver bdrv_host_floppy = { .bdrv_truncate = raw_truncate, .bdrv_getlength = raw_getlength, + .bdrv_get_alignment = raw_get_alignment, .bdrv_get_allocated_file_size = raw_get_allocated_file_size, @@ -1128,6 +1165,7 @@ static BlockDriver bdrv_host_cdrom = { .bdrv_truncate = raw_truncate, .bdrv_getlength = raw_getlength, + .bdrv_get_alignment = raw_get_alignment, .bdrv_get_allocated_file_size = raw_get_allocated_file_size, @@ -1247,6 +1285,7 @@ static BlockDriver bdrv_host_cdrom = { .bdrv_truncate = raw_truncate, .bdrv_getlength = raw_getlength, + .bdrv_get_alignment = raw_get_alignment, .bdrv_get_allocated_file_size = raw_get_allocated_file_size, diff --git a/block/raw-win32.c b/block/raw-win32.c index e4b0b75..f033037 100644 --- a/block/raw-win32.c +++ b/block/raw-win32.c @@ -96,6 +96,18 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags) overlapped |= FILE_FLAG_NO_BUFFERING; if (!(flags & BDRV_O_CACHE_WB)) overlapped |= FILE_FLAG_WRITE_THROUGH; + + if (filename[0] && filename[1] == ':') { + snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", filename[0]); + } else if (filename[0] == '\\' && filename[1] == '\\') { + s->drive_path[0] = 0; + } else { + /* Relative path. */ + char buf[MAX_PATH]; + GetCurrentDirectory(MAX_PATH, buf); + snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", buf[0]); + } + s->hfile = CreateFile(filename, access_flags, FILE_SHARE_READ, NULL, OPEN_EXISTING, overlapped, NULL); @@ -184,6 +196,37 @@ static int raw_truncate(BlockDriverState *bs, int64_t offset) return 0; } +static int raw_get_alignment(BlockDriverState *bs) +{ + BDRVRawState *s = bs->opaque; + DWORD sectorsPerCluster, freeClusters, totalClusters, count; + DISK_GEOMETRY_EX dg; + BOOL status; + + dg.Geometry.BytesPerSector = 512; + switch(s->type) { + case FTYPE_CD: + return 2048; + case FTYPE_HARDDISK: + status = DeviceIoControl(s->hfile, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, + NULL, 0, &dg, sizeof(dg), &count, NULL); + if (status != 0) { + break; + } + /* fall through */ + case FTYPE_FILE: + if (s->drive_path[0]) { + GetDiskFreeSpace(s->drive_path, §orsPerCluster, + &dg.Geometry.BytesPerSector, + &freeClusters, &totalClusters); + } + break; + default: + return -EIO; + } + return dg.Geometry.BytesPerSector; +} + static int64_t raw_getlength(BlockDriverState *bs) { BDRVRawState *s = bs->opaque; @@ -288,6 +331,7 @@ static BlockDriver bdrv_file = { .bdrv_truncate = raw_truncate, .bdrv_getlength = raw_getlength, + .bdrv_get_alignment = raw_get_alignment, .bdrv_get_allocated_file_size = raw_get_allocated_file_size, @@ -418,6 +462,7 @@ static BlockDriver bdrv_host_device = { .bdrv_co_flush_to_disk = raw_flush, .bdrv_getlength = raw_getlength, + .bdrv_get_alignment = raw_get_alignment, .bdrv_get_allocated_file_size = raw_get_allocated_file_size, }; -- 1.7.7.1