zonefs: Provide a splice-read wrapper

Provide a splice_read wrapper for zonefs.  This does some checks before
proceeding and locks the inode across the call to filemap_splice_read() and
a size check in case of truncation.  Splicing from direct I/O is handled by
the caller.

Signed-off-by: David Howells <dhowells@redhat.com>
cc: Christoph Hellwig <hch@lst.de>
cc: Al Viro <viro@zeniv.linux.org.uk>
cc: Jens Axboe <axboe@kernel.dk>
cc: Darrick J. Wong <djwong@kernel.org>
cc: linux-xfs@vger.kernel.org
cc: linux-fsdevel@vger.kernel.org
cc: linux-block@vger.kernel.org
cc: linux-mm@kvack.org
Acked-by: Damien Le Moal <dlemoal@kernel.org>
Link: https://lore.kernel.org/r/20230522135018.2742245-26-dhowells@redhat.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
David Howells 2023-05-22 14:50:12 +01:00 committed by Jens Axboe
parent 54919f94ec
commit 6ef48ec391
1 changed files with 39 additions and 1 deletions

View File

@ -752,6 +752,44 @@ inode_unlock:
return ret;
}
static ssize_t zonefs_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);
struct zonefs_inode_info *zi = ZONEFS_I(inode);
struct zonefs_zone *z = zonefs_inode_zone(inode);
loff_t isize;
ssize_t ret = 0;
/* Offline zones cannot be read */
if (unlikely(IS_IMMUTABLE(inode) && !(inode->i_mode & 0777)))
return -EPERM;
if (*ppos >= z->z_capacity)
return 0;
inode_lock_shared(inode);
/* Limit read operations to written data */
mutex_lock(&zi->i_truncate_mutex);
isize = i_size_read(inode);
if (*ppos >= isize)
len = 0;
else
len = min_t(loff_t, len, isize - *ppos);
mutex_unlock(&zi->i_truncate_mutex);
if (len > 0) {
ret = filemap_splice_read(in, ppos, pipe, len, flags);
if (ret == -EIO)
zonefs_io_error(inode, false);
}
inode_unlock_shared(inode);
return ret;
}
/*
* Write open accounting is done only for sequential files.
*/
@ -896,7 +934,7 @@ const struct file_operations zonefs_file_operations = {
.llseek = zonefs_file_llseek,
.read_iter = zonefs_file_read_iter,
.write_iter = zonefs_file_write_iter,
.splice_read = generic_file_splice_read,
.splice_read = zonefs_file_splice_read,
.splice_write = iter_file_splice_write,
.iopoll = iocb_bio_iopoll,
};