[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-Id: <1336416985-24605-3-git-send-email-tytso@mit.edu>
Date: Mon, 7 May 2012 14:56:22 -0400
From: Theodore Ts'o <tytso@....edu>
To: Ext4 Developers List <linux-ext4@...r.kernel.org>
Cc: ksumrall@...gle.com, Theodore Ts'o <tytso@....edu>
Subject: [PATCH 2/5] libext2fs: refactor Direct I/O alignment requirement calculations
Create a new function, ext2fs_get_dio_alignment(), which returns the
alignment requirements for direct I/O. This way we can factor out the
code from MMP and the Unix I/O manager. The two modules weren't
consistently calculating the alignment factors, and in particular MMP
would sometimes use a larger alignment factor than was strictly
necessary.
Signed-off-by: "Theodore Ts'o" <tytso@....edu>
---
lib/ext2fs/ext2fs.h | 1 +
lib/ext2fs/getsectsize.c | 26 ++++++++++++++++++++++++++
lib/ext2fs/mmp.c | 37 +++++++++----------------------------
lib/ext2fs/unix_io.c | 22 ++++++++--------------
4 files changed, 44 insertions(+), 42 deletions(-)
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index fda6ade..9a0e736 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -1213,6 +1213,7 @@ extern errcode_t ext2fs_get_device_size2(const char *file, int blocksize,
blk64_t *retblocks);
/* getsectsize.c */
+extern int ext2fs_get_dio_alignment(int fd);
errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize);
errcode_t ext2fs_get_device_phys_sectsize(const char *file, int *sectsize);
diff --git a/lib/ext2fs/getsectsize.c b/lib/ext2fs/getsectsize.c
index 30faecc..9c3f4a2 100644
--- a/lib/ext2fs/getsectsize.c
+++ b/lib/ext2fs/getsectsize.c
@@ -62,6 +62,32 @@ errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize)
}
/*
+ * Return desired alignment for direct I/O
+ */
+int ext2fs_get_dio_alignment(int fd)
+{
+ int align = 0;
+
+#ifdef BLKSSZGET
+ if (ioctl(fd, BLKSSZGET, &align) < 0)
+ align = 0;
+#endif
+
+#ifdef _SC_PAGESIZE
+ if (align <= 0)
+ align = sysconf(_SC_PAGESIZE);
+#endif
+#ifdef HAVE_GETPAGESIZE
+ if (align <= 0)
+ align = getpagesize();
+#endif
+ if (align <= 0)
+ align = 4096;
+
+ return align;
+}
+
+/*
* Returns the physical sector size of a device
*/
errcode_t ext2fs_get_device_phys_sectsize(const char *file, int *sectsize)
diff --git a/lib/ext2fs/mmp.c b/lib/ext2fs/mmp.c
index 49a11da..bb3772d 100644
--- a/lib/ext2fs/mmp.c
+++ b/lib/ext2fs/mmp.c
@@ -27,20 +27,6 @@
#include "ext2fs/ext2_fs.h"
#include "ext2fs/ext2fs.h"
-static int mmp_pagesize(void)
-{
-#ifdef _SC_PAGESIZE
- int sysval = sysconf(_SC_PAGESIZE);
- if (sysval > 0)
- return sysval;
-#endif /* _SC_PAGESIZE */
-#ifdef HAVE_GETPAGESIZE
- return getpagesize();
-#else
- return 4096;
-#endif
-}
-
#ifndef O_DIRECT
#define O_DIRECT 0
#endif
@@ -54,20 +40,6 @@ errcode_t ext2fs_mmp_read(ext2_filsys fs, blk64_t mmp_blk, void *buf)
(mmp_blk >= fs->super->s_blocks_count))
return EXT2_ET_MMP_BAD_BLOCK;
- if (fs->mmp_cmp == NULL) {
- /* O_DIRECT in linux 2.4: page aligned
- * O_DIRECT in linux 2.6: sector aligned
- * A filesystem cannot be created with blocksize < sector size,
- * or with blocksize > page_size. */
- int bufsize = fs->blocksize;
-
- if (bufsize < mmp_pagesize())
- bufsize = mmp_pagesize();
- retval = ext2fs_get_memalign(bufsize, bufsize, &fs->mmp_cmp);
- if (retval)
- return retval;
- }
-
/* ext2fs_open() reserves fd0,1,2 to avoid stdio collision, so checking
* mmp_fd <= 0 is OK to validate that the fd is valid. This opens its
* own fd to read the MMP block to ensure that it is using O_DIRECT,
@@ -81,6 +53,15 @@ errcode_t ext2fs_mmp_read(ext2_filsys fs, blk64_t mmp_blk, void *buf)
}
}
+ if (fs->mmp_cmp == NULL) {
+ int align = ext2fs_get_dio_alignment(fs->mmp_fd);
+
+ retval = ext2fs_get_memalign(fs->blocksize, align,
+ &fs->mmp_cmp);
+ if (retval)
+ return retval;
+ }
+
if (ext2fs_llseek(fs->mmp_fd, mmp_blk * fs->blocksize, SEEK_SET) !=
mmp_blk * fs->blocksize) {
retval = EXT2_ET_LLSEEK_FAILED;
diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c
index 3269392..8319eba 100644
--- a/lib/ext2fs/unix_io.c
+++ b/lib/ext2fs/unix_io.c
@@ -58,10 +58,6 @@
#define BLKROGET _IO(0x12, 94) /* Get read-only status (0 = read_write). */
#endif
-#if defined(__linux__) && defined(_IO) && !defined(BLKSSZGET)
-#define BLKSSZGET _IO(0x12,104)/* get block device sector size */
-#endif
-
#undef ALIGN_DEBUG
#include "ext2_fs.h"
@@ -485,11 +481,15 @@ static errcode_t unix_open(const char *name, int flags, io_channel *channel)
if (flags & IO_FLAG_EXCLUSIVE)
open_flags |= O_EXCL;
#if defined(O_DIRECT)
- if (flags & IO_FLAG_DIRECT_IO)
+ if (flags & IO_FLAG_DIRECT_IO) {
open_flags |= O_DIRECT;
+ io->align = ext2fs_get_dio_alignment(data->dev);
+ }
#elif defined(F_NOCACHE)
- if (flags & IO_FLAG_DIRECT_IO)
+ if (flags & IO_FLAG_DIRECT_IO) {
f_nocache = F_NOCACHE;
+ io->align = 4096;
+ }
#endif
data->flags = flags;
@@ -519,13 +519,6 @@ static errcode_t unix_open(const char *name, int flags, io_channel *channel)
io->flags |= CHANNEL_FLAGS_DISCARD_ZEROES;
}
-#ifdef BLKSSZGET
- if (flags & IO_FLAG_DIRECT_IO) {
- if (ioctl(data->dev, BLKSSZGET, &io->align) != 0)
- io->align = io->block_size;
- }
-#endif
-
#ifdef BLKDISCARDZEROES
ioctl(data->dev, BLKDISCARDZEROES, &zeroes);
if (zeroes)
@@ -537,7 +530,8 @@ static errcode_t unix_open(const char *name, int flags, io_channel *channel)
* Some operating systems require that the buffers be aligned,
* regardless of O_DIRECT
*/
- io->align = 512;
+ if (!io->align)
+ io->align = 512;
#endif
--
1.7.10.rc3
--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists