diff options
| author | Viacheslav Dubeyko <slava@dubeyko.com> | 2026-07-24 15:27:45 -0700 |
|---|---|---|
| committer | Christian Brauner <brauner@kernel.org> | 2026-07-27 11:43:15 +0200 |
| commit | b924d8d4e54f179bccd9f28f57a2c4fbb570c04a (patch) | |
| tree | 2ea9342d51073b860f44ad40301448314cc344af | |
| parent | e7b2c51c3fedd68bf97d9a49cfbe76b240aee41d (diff) | |
| download | linux-next-b924d8d4e54f179bccd9f28f57a2c4fbb570c04a.tar.gz linux-next-b924d8d4e54f179bccd9f28f57a2c4fbb570c04a.zip | |
nilfs2: switch O_DIRECT reads to iomap
Wire the read-only nilfs_iomap_ops added in the previous patch into
the O_DIRECT read path, and eliminate blockdev_direct_IO() from
nilfs2 entirely:
- nilfs_file_open() now sets FMODE_CAN_ODIRECT explicitly, since
permission to open the file O_DIRECT was previously implied by
aops->direct_IO being non-NULL.
- nilfs_file_read_iter() dispatches O_DIRECT reads to iomap_dio_rw()
using nilfs_iomap_ops; everything else still goes through
generic_file_read_iter() as before.
- nilfs_file_write_iter() strips IOCB_DIRECT and falls through to
generic_file_write_iter()'s ordinary buffered path. NILFS2 cannot
perform true direct I/O writes: new blocks are delay-allocated and
only given a real disk address by the segment constructor, which
works on buffer_head lists, not iomap. This reproduces today's
actual behavior: the old nilfs_direct_IO() already just returned 0
for WRITE.
- nilfs_direct_IO() and the .direct_IO callback on nilfs_aops are
removed.
- drop the unnecessary "select LEGACY_DIRECT_IO" from Kconfig
in favor of "select FS_IOMAP".
Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com>
Link: https://patch.msgid.link/20260724222745.2107464-3-slava@dubeyko.com
Acked-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
cc: Christoph Hellwig <hch@lst.de>
cc: Ryusuke Konishi <konishi.ryusuke@gmail.com>
cc: linux-nilfs@vger.kernel.org
cc: linux-fsdevel@vger.kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
| -rw-r--r-- | fs/nilfs2/Kconfig | 2 | ||||
| -rw-r--r-- | fs/nilfs2/file.c | 40 | ||||
| -rw-r--r-- | fs/nilfs2/inode.c | 13 |
3 files changed, 38 insertions, 17 deletions
diff --git a/fs/nilfs2/Kconfig b/fs/nilfs2/Kconfig index 7dae168e346e..0a5ace60e6ab 100644 --- a/fs/nilfs2/Kconfig +++ b/fs/nilfs2/Kconfig @@ -3,7 +3,7 @@ config NILFS2_FS tristate "NILFS2 file system support" select BUFFER_HEAD select CRC32 - select LEGACY_DIRECT_IO + select FS_IOMAP help NILFS2 is a log-structured file system (LFS) supporting continuous snapshotting. In addition to versioning capability of the entire diff --git a/fs/nilfs2/file.c b/fs/nilfs2/file.c index f93b68c4877c..ad2e87c049c9 100644 --- a/fs/nilfs2/file.c +++ b/fs/nilfs2/file.c @@ -10,9 +10,12 @@ #include <linux/fs.h> #include <linux/filelock.h> #include <linux/mm.h> +#include <linux/uio.h> +#include <linux/iomap.h> #include <linux/writeback.h> #include "nilfs.h" #include "segment.h" +#include "iomap.h" int nilfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) { @@ -133,20 +136,51 @@ static int nilfs_file_mmap_prepare(struct vm_area_desc *desc) return 0; } +static int nilfs_file_open(struct inode *inode, struct file *file) +{ + file->f_mode |= FMODE_CAN_ODIRECT; + return generic_file_open(inode, file); +} + +static ssize_t nilfs_file_read_iter(struct kiocb *iocb, struct iov_iter *to) +{ + if (iocb->ki_flags & IOCB_DIRECT) { + return iomap_dio_rw(iocb, to, &nilfs_iomap_ops, + NULL, 0, NULL, 0); + } else + return generic_file_read_iter(iocb, to); +} + +static ssize_t nilfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) +{ + /* + * NILFS2 cannot perform true direct I/O writes: new blocks are + * delay-allocated and are only given a real disk address when + * the segment constructor writes them out as part of a log, + * which works directly on buffer_head lists rather than + * through iomap. Fall back to the ordinary buffered write path + * for O_DIRECT writes. + */ + if (iocb->ki_flags & IOCB_DIRECT) + iocb->ki_flags &= ~IOCB_DIRECT; + + return generic_file_write_iter(iocb, from); +} + /* * We have mostly NULL's here: the current defaults are ok for * the nilfs filesystem. */ const struct file_operations nilfs_file_operations = { .llseek = generic_file_llseek, - .read_iter = generic_file_read_iter, - .write_iter = generic_file_write_iter, + .read_iter = nilfs_file_read_iter, + .write_iter = nilfs_file_write_iter, .unlocked_ioctl = nilfs_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = nilfs_compat_ioctl, #endif /* CONFIG_COMPAT */ .mmap_prepare = nilfs_file_mmap_prepare, - .open = generic_file_open, + .open = nilfs_file_open, /* .release = nilfs_release_file, */ .fsync = nilfs_sync_file, .splice_read = filemap_splice_read, diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 51f7e125a311..f4a9d9ea9c3f 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -257,18 +257,6 @@ static int nilfs_write_end(const struct kiocb *iocb, return err ? : copied; } -static ssize_t -nilfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) -{ - struct inode *inode = file_inode(iocb->ki_filp); - - if (iov_iter_rw(iter) == WRITE) - return 0; - - /* Needs synchronization with the cleaner */ - return blockdev_direct_IO(iocb, inode, iter, nilfs_get_block); -} - const struct address_space_operations nilfs_aops = { .read_folio = nilfs_read_folio, .writepages = nilfs_writepages, @@ -277,7 +265,6 @@ const struct address_space_operations nilfs_aops = { .write_begin = nilfs_write_begin, .write_end = nilfs_write_end, .invalidate_folio = block_invalidate_folio, - .direct_IO = nilfs_direct_IO, .migrate_folio = buffer_migrate_folio_norefs, .is_partially_uptodate = block_is_partially_uptodate, }; |
