Re: [Qemu-devel] [PATCH v2 08/24] raw: Probe required direct I/O alignment

2014-01-11 Thread Max Reitz

On 13.12.2013 14:22, Kevin Wolf wrote:

From: Paolo Bonzini pbonz...@redhat.com

Add a bs-request_alignment field that contains the required
offset/length alignment for I/O requests and fill it in the raw block
drivers. Use ioctls if possible, else see what alignment it takes for
O_DIRECT to succeed.

While at it, also expose the memory alignment requirements, which may be
(and in practice are) different from the disk alignment requirements.

Signed-off-by: Paolo Bonzini pbonz...@redhat.com
Signed-off-by: Kevin Wolf kw...@redhat.com
---
  block.c   |   3 ++
  block/raw-posix.c | 102 ++
  block/raw-win32.c |  41 +++
  include/block/block_int.h |   3 ++
  4 files changed, 132 insertions(+), 17 deletions(-)


Reviewed-by: Max Reitz mre...@redhat.com



Re: [Qemu-devel] [PATCH v2 08/24] raw: Probe required direct I/O alignment

2013-12-23 Thread Wenchao Xia
I am not sure the win32 API usage, except that part, patch looks OK.




[Qemu-devel] [PATCH v2 08/24] raw: Probe required direct I/O alignment

2013-12-13 Thread Kevin Wolf
From: Paolo Bonzini pbonz...@redhat.com

Add a bs-request_alignment field that contains the required
offset/length alignment for I/O requests and fill it in the raw block
drivers. Use ioctls if possible, else see what alignment it takes for
O_DIRECT to succeed.

While at it, also expose the memory alignment requirements, which may be
(and in practice are) different from the disk alignment requirements.

Signed-off-by: Paolo Bonzini pbonz...@redhat.com
Signed-off-by: Kevin Wolf kw...@redhat.com
---
 block.c   |   3 ++
 block/raw-posix.c | 102 ++
 block/raw-win32.c |  41 +++
 include/block/block_int.h |   3 ++
 4 files changed, 132 insertions(+), 17 deletions(-)

diff --git a/block.c b/block.c
index 3504d17..b86e754 100644
--- a/block.c
+++ b/block.c
@@ -813,6 +813,7 @@ static int bdrv_open_common(BlockDriverState *bs, 
BlockDriverState *file,
 
 bs-open_flags = flags;
 bs-guest_block_size = 512;
+bs-request_alignment = 512;
 bs-zero_beyond_eof = true;
 open_flags = bdrv_open_flags(bs, flags);
 bs-read_only = !(open_flags  BDRV_O_RDWR);
@@ -881,6 +882,8 @@ static int bdrv_open_common(BlockDriverState *bs, 
BlockDriverState *file,
 }
 
 bdrv_refresh_limits(bs);
+assert(bdrv_opt_mem_align(bs) != 0);
+assert(bs-request_alignment != 0);
 
 #ifndef _WIN32
 if (bs-is_temporary) {
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 10c6b34..e8e75a7 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -127,6 +127,8 @@ typedef struct BDRVRawState {
 int fd;
 int type;
 int open_flags;
+size_t buf_align;
+
 #if defined(__linux__)
 /* linux floppy specific */
 int64_t fd_open_time;
@@ -213,6 +215,76 @@ static int raw_normalize_devicepath(const char **filename)
 }
 #endif
 
+static void raw_probe_alignment(BlockDriverState *bs)
+{
+BDRVRawState *s = bs-opaque;
+char *buf;
+unsigned int sector_size;
+
+/* For /dev/sg devices the alignment is not really used.
+   With buffered I/O, we don't have any restrictions. */
+if (bs-sg || !(s-open_flags  O_DIRECT)) {
+bs-request_alignment = 1;
+s-buf_align = 1;
+return;
+}
+
+/* Try a few ioctls to get the right size */
+bs-request_alignment = 0;
+s-buf_align = 0;
+
+#ifdef BLKSSZGET
+if (ioctl(s-fd, BLKSSZGET, sector_size) = 0) {
+bs-request_alignment = sector_size;
+}
+#endif
+#ifdef DKIOCGETBLOCKSIZE
+if (ioctl(s-fd, DKIOCGETBLOCKSIZE, sector_size) = 0) {
+bs-request_alignment = sector_size;
+}
+#endif
+#ifdef DIOCGSECTORSIZE
+if (ioctl(s-fd, DIOCGSECTORSIZE, sector_size) = 0) {
+bs-request_alignment = sector_size;
+}
+#endif
+#ifdef CONFIG_XFS
+if (s-is_xfs) {
+struct dioattr da;
+if (xfsctl(NULL, s-fd, XFS_IOC_DIOINFO, da) = 0) {
+bs-request_alignment = da.d_miniosz;
+/* The kernel returns wrong information for d_mem */
+/* s-buf_align = da.d_mem; */
+}
+}
+#endif
+
+/* If we could not get the sizes so far, we can only guess them */
+if (!s-buf_align) {
+size_t align;
+buf = qemu_memalign(MAX_BLOCKSIZE, 2 * MAX_BLOCKSIZE);
+for (align = 512; align = MAX_BLOCKSIZE; align = 1) {
+if (pread(s-fd, buf + align, MAX_BLOCKSIZE, 0) = 0) {
+s-buf_align = align;
+break;
+}
+}
+qemu_vfree(buf);
+}
+
+if (!bs-request_alignment) {
+size_t align;
+buf = qemu_memalign(s-buf_align, MAX_BLOCKSIZE);
+for (align = 512; align = MAX_BLOCKSIZE; align = 1) {
+if (pread(s-fd, buf, align, 0) = 0) {
+bs-request_alignment = align;
+break;
+}
+}
+qemu_vfree(buf);
+}
+}
+
 static void raw_parse_flags(int bdrv_flags, int *open_flags)
 {
 assert(open_flags != NULL);
@@ -463,7 +535,6 @@ static int raw_reopen_prepare(BDRVReopenState *state,
 return ret;
 }
 
-
 static void raw_reopen_commit(BDRVReopenState *state)
 {
 BDRVRawReopenState *raw_s = state-opaque;
@@ -499,23 +570,15 @@ static void raw_reopen_abort(BDRVReopenState *state)
 state-opaque = NULL;
 }
 
+static int raw_refresh_limits(BlockDriverState *bs)
+{
+BDRVRawState *s = bs-opaque;
 
-/* XXX: use host sector size if necessary with:
-#ifdef DIOCGSECTORSIZE
-{
-unsigned int sectorsize = 512;
-if (!ioctl(fd, DIOCGSECTORSIZE, sectorsize) 
-sectorsize  bufsize)
-bufsize = sectorsize;
-}
-#endif
-#ifdef CONFIG_COCOA
-uint32_t blockSize = 512;
-if ( !ioctl( fd, DKIOCGETBLOCKSIZE, blockSize )  blockSize  
bufsize) {
-bufsize = blockSize;
-}
-#endif
-*/
+raw_probe_alignment(bs);
+bs-bl.opt_mem_alignment = s-buf_align;
+
+return 0;
+}
 
 static ssize_t