Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ocfs2: Provide a splice-read wrapper

Provide a splice_read wrapper 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@redhat.com>
Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
cc: Christoph Hellwig <hch@lst.de>
cc: Al Viro <viro@zeniv.linux.org.uk>
cc: Jens Axboe <axboe@kernel.dk>
cc: Mark Fasheh <mark@fasheh.com>
cc: Joel Becker <jlbec@evilplan.org>
cc: ocfs2-devel@oss.oracle.com
cc: linux-fsdevel@vger.kernel.org
cc: linux-block@vger.kernel.org
cc: linux-mm@kvack.org
Link: https://lore.kernel.org/r/20230522135018.2742245-23-dhowells@redhat.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

David Howells and committed by
Jens Axboe
94aca682 51494398

+42 -2
+39 -2
fs/ocfs2/file.c
··· 2552 2552 * 2553 2553 * Take and drop the meta data lock to update inode fields 2554 2554 * like i_size. This allows the checks down below 2555 - * generic_file_read_iter() a chance of actually working. 2555 + * copy_splice_read() a chance of actually working. 2556 2556 */ 2557 2557 ret = ocfs2_inode_lock_atime(inode, filp->f_path.mnt, &lock_level, 2558 2558 !nowait); ··· 2578 2578 if (rw_level != -1) 2579 2579 ocfs2_rw_unlock(inode, rw_level); 2580 2580 2581 + return ret; 2582 + } 2583 + 2584 + static ssize_t ocfs2_file_splice_read(struct file *in, loff_t *ppos, 2585 + struct pipe_inode_info *pipe, 2586 + size_t len, unsigned int flags) 2587 + { 2588 + struct inode *inode = file_inode(in); 2589 + ssize_t ret = 0; 2590 + int lock_level = 0; 2591 + 2592 + trace_ocfs2_file_splice_read(inode, in, in->f_path.dentry, 2593 + (unsigned long long)OCFS2_I(inode)->ip_blkno, 2594 + in->f_path.dentry->d_name.len, 2595 + in->f_path.dentry->d_name.name, 2596 + flags); 2597 + 2598 + /* 2599 + * We're fine letting folks race truncates and extending writes with 2600 + * read across the cluster, just like they can locally. Hence no 2601 + * rw_lock during read. 2602 + * 2603 + * Take and drop the meta data lock to update inode fields like i_size. 2604 + * This allows the checks down below filemap_splice_read() a chance of 2605 + * actually working. 2606 + */ 2607 + ret = ocfs2_inode_lock_atime(inode, in->f_path.mnt, &lock_level, 1); 2608 + if (ret < 0) { 2609 + if (ret != -EAGAIN) 2610 + mlog_errno(ret); 2611 + goto bail; 2612 + } 2613 + ocfs2_inode_unlock(inode, lock_level); 2614 + 2615 + ret = filemap_splice_read(in, ppos, pipe, len, flags); 2616 + trace_filemap_splice_read_ret(ret); 2617 + bail: 2581 2618 return ret; 2582 2619 } 2583 2620 ··· 2781 2744 #endif 2782 2745 .lock = ocfs2_lock, 2783 2746 .flock = ocfs2_flock, 2784 - .splice_read = generic_file_splice_read, 2747 + .splice_read = ocfs2_file_splice_read, 2785 2748 .splice_write = iter_file_splice_write, 2786 2749 .fallocate = ocfs2_fallocate, 2787 2750 .remap_file_range = ocfs2_remap_file_range,
+3
fs/ocfs2/ocfs2_trace.h
··· 1319 1319 1320 1320 DEFINE_OCFS2_FILE_OPS(ocfs2_file_read_iter); 1321 1321 1322 + DEFINE_OCFS2_FILE_OPS(ocfs2_file_splice_read); 1323 + 1322 1324 DEFINE_OCFS2_ULL_ULL_ULL_EVENT(ocfs2_truncate_file); 1323 1325 1324 1326 DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_truncate_file_error); ··· 1472 1470 ); 1473 1471 1474 1472 DEFINE_OCFS2_INT_EVENT(generic_file_read_iter_ret); 1473 + DEFINE_OCFS2_INT_EVENT(filemap_splice_read_ret); 1475 1474 1476 1475 /* End of trace events for fs/ocfs2/file.c. */ 1477 1476