tmpfs: trivial support for direct IO

JIRA: https://issues.redhat.com/browse/RHEL-27743

This patch is a backport of the following upstream commit:
commit e88e0d366f9cfbb810b0c8509dc5d130d5a53e02
Author: Hugh Dickins <hughd@google.com>
Date:   Thu Aug 10 23:27:07 2023 -0700

    tmpfs: trivial support for direct IO

    Depending upon your philosophical viewpoint, either tmpfs always does
    direct IO, or it cannot ever do direct IO; but whichever, if tmpfs is to
    stand in for a more sophisticated filesystem, it can be helpful for tmpfs
    to support O_DIRECT.  So, give tmpfs a shmem_file_open() method, to set
    the FMODE_CAN_ODIRECT flag: then unchanged shmem_file_read_iter() and new
    shmem_file_write_iter() do the work (without any shmem_direct_IO() stub).

    Perhaps later, once the direct_IO method has been eliminated from all
    filesystems, generic_file_write_iter() will be such that tmpfs can again
    use it, even for O_DIRECT.

    xfstests auto generic which were not run on tmpfs before but now pass:
    036 091 113 125 130 133 135 198 207 208 209 210 211 212 214 226 239 263
    323 355 391 406 412 422 427 446 451 465 551 586 591 609 615 647 708 729
    with no new failures.

    LTP dio tests which were not run on tmpfs before but now pass:
    dio01 through dio30, except for dio04 and dio10, which fail because
    tmpfs dio read and write allow odd count: tmpfs could be made stricter,
    but would that be an improvement?

    Signed-off-by: Hugh Dickins <hughd@google.com>
    Reviewed-by: Christoph Hellwig <hch@lst.de>
    Reviewed-by: Jan Kara <jack@suse.cz>
    Message-Id: <6f2742-6f1f-cae9-7c5b-ed20fc53215@google.com>
    Signed-off-by: Christian Brauner <brauner@kernel.org>

Signed-off-by: Rafael Aquini <raquini@redhat.com>
This commit is contained in:
Rafael Aquini 2024-09-27 10:45:01 -04:00
parent 6f0996c6e1
commit db6591e712
1 changed files with 30 additions and 2 deletions

View File

@ -2416,6 +2416,12 @@ static int shmem_mmap(struct file *file, struct vm_area_struct *vma)
return 0;
}
static int shmem_file_open(struct inode *inode, struct file *file)
{
file->f_mode |= FMODE_CAN_ODIRECT;
return generic_file_open(inode, file);
}
#ifdef CONFIG_TMPFS_XATTR
static int shmem_initxattrs(struct inode *, const struct xattr *, void *);
@ -2859,6 +2865,28 @@ static ssize_t shmem_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
return retval ? retval : error;
}
static ssize_t shmem_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
{
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
ssize_t ret;
inode_lock(inode);
ret = generic_write_checks(iocb, from);
if (ret <= 0)
goto unlock;
ret = file_remove_privs(file);
if (ret)
goto unlock;
ret = file_update_time(file);
if (ret)
goto unlock;
ret = generic_perform_write(iocb, from);
unlock:
inode_unlock(inode);
return ret;
}
static bool zero_pipe_buf_get(struct pipe_inode_info *pipe,
struct pipe_buffer *buf)
{
@ -4391,12 +4419,12 @@ EXPORT_SYMBOL(shmem_aops);
static const struct file_operations shmem_file_operations = {
.mmap = shmem_mmap,
.open = generic_file_open,
.open = shmem_file_open,
.get_unmapped_area = shmem_get_unmapped_area,
#ifdef CONFIG_TMPFS
.llseek = shmem_file_llseek,
.read_iter = shmem_file_read_iter,
.write_iter = generic_file_write_iter,
.write_iter = shmem_file_write_iter,
.fsync = noop_fsync,
.splice_read = shmem_file_splice_read,
.splice_write = iter_file_splice_write,