David Howells
2023-May-19 07:40 UTC
[Ocfs2-devel] [PATCH v20 19/32] ocfs2: Provide a splice-read stub
Provide a splice_read stub for ocfs2. This emits trace lines and does an atime lock/update before calling filemap_splice_read(). It doesn't do this for around direct_splice_read() as that will call ->read_iter(). A couple of new tracepoints are added for this purpose. Signed-off-by: David Howells <dhowells at redhat.com> cc: Christoph Hellwig <hch at lst.de> cc: Al Viro <viro at zeniv.linux.org.uk> cc: Jens Axboe <axboe at kernel.dk> cc: Mark Fasheh <mark at fasheh.com> cc: Joel Becker <jlbec at evilplan.org> cc: Joseph Qi <joseph.qi at linux.alibaba.com> cc: ocfs2-devel at oss.oracle.com cc: linux-fsdevel at vger.kernel.org cc: linux-block at vger.kernel.org cc: linux-mm at kvack.org --- fs/ocfs2/file.c | 42 +++++++++++++++++++++++++++++++++++++++++- fs/ocfs2/ocfs2_trace.h | 3 +++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index efb09de4343d..27c54a71ec57 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -2581,6 +2581,46 @@ static ssize_t ocfs2_file_read_iter(struct kiocb *iocb, return ret; } +static ssize_t ocfs2_file_splice_read(struct file *in, loff_t *ppos, + struct pipe_inode_info *pipe, + size_t len, unsigned int flags) +{ + struct inode *inode = file_inode(in); + ssize_t ret = 0; + int lock_level = 0; + + trace_ocfs2_file_splice_read(inode, in, in->f_path.dentry, + (unsigned long long)OCFS2_I(inode)->ip_blkno, + in->f_path.dentry->d_name.len, + in->f_path.dentry->d_name.name, + 0); + + if (in->f_flags & O_DIRECT) + return direct_splice_read(in, ppos, pipe, len, flags); + + /* + * We're fine letting folks race truncates and extending writes with + * read across the cluster, just like they can locally. Hence no + * rw_lock during read. + * + * Take and drop the meta data lock to update inode fields like i_size. + * This allows the checks down below generic_file_splice_read() a + * chance of actually working. + */ + ret = ocfs2_inode_lock_atime(inode, in->f_path.mnt, &lock_level, true); + if (ret < 0) { + if (ret != -EAGAIN) + mlog_errno(ret); + goto bail; + } + ocfs2_inode_unlock(inode, lock_level); + + ret = filemap_splice_read(in, ppos, pipe, len, flags); + trace_filemap_splice_read_ret(ret); +bail: + return ret; +} + /* Refer generic_file_llseek_unlocked() */ static loff_t ocfs2_file_llseek(struct file *file, loff_t offset, int whence) { @@ -2744,7 +2784,7 @@ const struct file_operations ocfs2_fops = { #endif .lock = ocfs2_lock, .flock = ocfs2_flock, - .splice_read = generic_file_splice_read, + .splice_read = ocfs2_file_splice_read, .splice_write = iter_file_splice_write, .fallocate = ocfs2_fallocate, .remap_file_range = ocfs2_remap_file_range, diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index dc4bce1649c1..b8c3d1702076 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -1319,6 +1319,8 @@ DEFINE_OCFS2_FILE_OPS(ocfs2_file_splice_write); DEFINE_OCFS2_FILE_OPS(ocfs2_file_read_iter); +DEFINE_OCFS2_FILE_OPS(ocfs2_file_splice_read); + DEFINE_OCFS2_ULL_ULL_ULL_EVENT(ocfs2_truncate_file); DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_truncate_file_error); @@ -1470,6 +1472,7 @@ TRACE_EVENT(ocfs2_prepare_inode_for_write, ); DEFINE_OCFS2_INT_EVENT(generic_file_read_iter_ret); +DEFINE_OCFS2_INT_EVENT(filemap_splice_read_ret); /* End of trace events for fs/ocfs2/file.c. */
Reasonably Related Threads
- [PATCH v21 22/30] ocfs2: Provide a splice-read stub
- [PATCH V8 21/33] ocfs2: add support for read_iter and write_iter
- [PATCH V5 19/30] ocfs2: add support for read_iter, write_iter, and direct_IO_bvec
- [PATCH] ocfs2: Update atime in splice read if necessary.
- [PATCH V3 RESENT] ocfs2: lighten up allocate transaction