[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC PATCH 2/3] raw: implement raw_get_alignment
From: |
Paolo Bonzini |
Subject: |
[Qemu-devel] [RFC PATCH 2/3] raw: implement raw_get_alignment |
Date: |
Wed, 23 Nov 2011 17:51:26 +0100 |
Signed-off-by: Paolo Bonzini <address@hidden>
---
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