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@mit.edu>
This commit is contained in:
Theodore Ts'o 2012-05-07 13:25:44 -04:00
parent 0a05b90330
commit dd0a2679dd
4 changed files with 44 additions and 42 deletions

View File

@ -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);

View File

@ -61,6 +61,32 @@ errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize)
return 0;
}
/*
* 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
*/

View File

@ -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;

View File

@ -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