2023-05-20 01:12:01

by David Howells

[permalink] [raw]
Subject: [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 <[email protected]>
cc: Christoph Hellwig <[email protected]>
cc: Al Viro <[email protected]>
cc: Jens Axboe <[email protected]>
cc: Mark Fasheh <[email protected]>
cc: Joel Becker <[email protected]>
cc: Joseph Qi <[email protected]>
cc: [email protected]
cc: [email protected]
cc: [email protected]
cc: [email protected]
---
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. */




2023-05-22 03:12:46

by Joseph Qi

[permalink] [raw]
Subject: Re: [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 <[email protected]>
> cc: Christoph Hellwig <[email protected]>
> cc: Al Viro <[email protected]>
> cc: Jens Axboe <[email protected]>
> cc: Mark Fasheh <[email protected]>
> cc: Joel Becker <[email protected]>
> cc: Joseph Qi <[email protected]>
> cc: [email protected]
> cc: [email protected]
> cc: [email protected]
> cc: [email protected]
> ---
> 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() a

Now 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. */
>

2023-05-22 06:43:37

by David Howells

[permalink] [raw]
Subject: Re: [PATCH v21 22/30] ocfs2: Provide a splice-read stub

Joseph Qi <[email protected]> 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


2023-05-22 06:55:40

by Joseph Qi

[permalink] [raw]
Subject: Re: [PATCH v21 22/30] ocfs2: Provide a splice-read stub



On 5/22/23 2:28 PM, David Howells wrote:
> Joseph Qi <[email protected]> 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.
>

Oops, missed the patch 7 of the series since I've only received this
one:(
Have checked it on maillist, it's fine for me now.

Thanks,
Joseph

2023-05-22 07:01:28

by David Howells

[permalink] [raw]
Subject: Re: [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);


2023-05-22 07:11:06

by Joseph Qi

[permalink] [raw]
Subject: Re: [PATCH v21 22/30] ocfs2: Provide a splice-read stub



On 5/22/23 2:49 PM, David Howells wrote:
> So something like the attached changes? Any suggestions as to how to improve
> the comments?
>

Looks fine to me now. Thanks.

Reviewed-by: Joseph Qi <[email protected]>

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