David Howells
2023-May-20  00:00 UTC
[Ocfs2-devel] [PATCH v21 22/30] 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().  Splicing from
direct I/O is handled by the caller.
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        | 39 ++++++++++++++++++++++++++++++++++++++-
 fs/ocfs2/ocfs2_trace.h |  3 +++
 2 files changed, 41 insertions(+), 1 deletion(-)
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index efb09de4343d..f7e00b5689d5 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -2581,6 +2581,43 @@ 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);
+
+	/*
+	 * 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 +2781,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. */
Joseph Qi
2023-May-22  02:49 UTC
[Ocfs2-devel] [PATCH v21 22/30] ocfs2: Provide a splice-read stub
On 5/20/23 8:00 AM, David Howells wrote:> Provide a splice_read stub for ocfs2. This emits trace lines and does an > atime lock/update before calling filemap_splice_read(). Splicing from > direct I/O is handled by the caller. > > 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 | 39 ++++++++++++++++++++++++++++++++++++++- > fs/ocfs2/ocfs2_trace.h | 3 +++ > 2 files changed, 41 insertions(+), 1 deletion(-) > > diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c > index efb09de4343d..f7e00b5689d5 100644 > --- a/fs/ocfs2/file.c > +++ b/fs/ocfs2/file.c > @@ -2581,6 +2581,43 @@ 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);Better also trace flags here.> + > + /* > + * 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() aNow it calls filemap_splice_read().> + * chance of actually working. > + */ > + ret = ocfs2_inode_lock_atime(inode, in->f_path.mnt, &lock_level, true);Since prototype is 'int wait', so directly passing '1' seems more appropriate.> + if (ret < 0) { > + if (ret != -EAGAIN) > + mlog_errno(ret); > + goto bail; > + } > + ocfs2_inode_unlock(inode, lock_level); > +Don't see direct IO logic now. Am I missing something? Thanks, Joseph> + 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 +2781,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. */ >
David Howells
2023-May-22  06:28 UTC
[Ocfs2-devel] [PATCH v21 22/30] ocfs2: Provide a splice-read stub
Joseph Qi <joseph.qi at linux.alibaba.com> wrote:> Don't see direct IO logic now. Am I missing something?See that patch description ;-) Provide a splice_read stub for ocfs2. This emits trace lines and does an atime lock/update before calling filemap_splice_read(). Splicing from direct I/O is handled by the caller. David
David Howells
2023-May-22  06:49 UTC
[Ocfs2-devel] [PATCH v21 22/30] ocfs2: Provide a splice-read stub
So something like the attached changes?  Any suggestions as to how to improve
the comments?
David
---
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index f7e00b5689d5..86add13b5f23 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -2552,7 +2552,7 @@ static ssize_t ocfs2_file_read_iter(struct kiocb *iocb,
 	 *
 	 * Take and drop the meta data lock to update inode fields
 	 * like i_size. This allows the checks down below
-	 * generic_file_read_iter() a chance of actually working.
+	 * copy_splice_read() a chance of actually working.
 	 */
 	ret = ocfs2_inode_lock_atime(inode, filp->f_path.mnt, &lock_level,
 				     !nowait);
@@ -2593,7 +2593,7 @@ static ssize_t ocfs2_file_splice_read(struct file *in,
loff_t *ppos,
 				     (unsigned long long)OCFS2_I(inode)->ip_blkno,
 				     in->f_path.dentry->d_name.len,
 				     in->f_path.dentry->d_name.name,
-				     0);
+				     flags);
 
 	/*
 	 * We're fine letting folks race truncates and extending writes with
@@ -2601,10 +2601,10 @@ static ssize_t ocfs2_file_splice_read(struct file *in,
loff_t *ppos,
 	 * 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.
+	 * This allows the checks down below filemap_splice_read() a chance of
+	 * actually working.
 	 */
-	ret = ocfs2_inode_lock_atime(inode, in->f_path.mnt, &lock_level, true);
+	ret = ocfs2_inode_lock_atime(inode, in->f_path.mnt, &lock_level, 1);
 	if (ret < 0) {
 		if (ret != -EAGAIN)
 			mlog_errno(ret);
Reasonably Related Threads
- [PATCH v20 19/32] 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 1/2] ocfs2: correct return value of ocfs2_local_free_info()