You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'work.splice_read' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull VFS splice updates from Al Viro: "There's a bunch of branches this cycle, both mine and from other folks and I'd rather send pull requests separately. This one is the conversion of ->splice_read() to ITER_PIPE iov_iter (and introduction of such). Gets rid of a lot of code in fs/splice.c and elsewhere; there will be followups, but these are for the next cycle... Some pipe/splice-related cleanups from Miklos in the same branch as well" * 'work.splice_read' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: pipe: fix comment in pipe_buf_operations pipe: add pipe_buf_steal() helper pipe: add pipe_buf_confirm() helper pipe: add pipe_buf_release() helper pipe: add pipe_buf_get() helper relay: simplify relay_file_read() switch default_file_splice_read() to use of pipe-backed iov_iter switch generic_file_splice_read() to use of ->read_iter() new iov_iter flavour: pipe-backed fuse_dev_splice_read(): switch to add_to_pipe() skb_splice_bits(): get rid of callback new helper: add_to_pipe() splice: lift pipe_lock out of splice_to_pipe() splice: switch get_iovec_page_array() to iov_iter splice_to_pipe(): don't open-code wakeup_pipe_readers() consistent treatment of EFAULT on O_DIRECT read/write
This commit is contained in:
@@ -889,7 +889,7 @@ static int pipe_to_sg(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
|
||||
return 0;
|
||||
|
||||
/* Try lock this page */
|
||||
if (buf->ops->steal(pipe, buf) == 0) {
|
||||
if (pipe_buf_steal(pipe, buf) == 0) {
|
||||
/* Get reference and unlock page for moving */
|
||||
get_page(buf->page);
|
||||
unlock_page(buf->page);
|
||||
|
||||
@@ -1138,45 +1138,31 @@ restart:
|
||||
range_lock_init(&range, *ppos, *ppos + count - 1);
|
||||
|
||||
vio->vui_fd = LUSTRE_FPRIVATE(file);
|
||||
vio->vui_io_subtype = args->via_io_subtype;
|
||||
vio->vui_iter = args->u.normal.via_iter;
|
||||
vio->vui_iocb = args->u.normal.via_iocb;
|
||||
/*
|
||||
* Direct IO reads must also take range lock,
|
||||
* or multiple reads will try to work on the same pages
|
||||
* See LU-6227 for details.
|
||||
*/
|
||||
if (((iot == CIT_WRITE) ||
|
||||
(iot == CIT_READ && (file->f_flags & O_DIRECT))) &&
|
||||
!(vio->vui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) {
|
||||
CDEBUG(D_VFSTRACE, "Range lock [%llu, %llu]\n",
|
||||
range.rl_node.in_extent.start,
|
||||
range.rl_node.in_extent.end);
|
||||
result = range_lock(&lli->lli_write_tree,
|
||||
&range);
|
||||
if (result < 0)
|
||||
goto out;
|
||||
|
||||
switch (vio->vui_io_subtype) {
|
||||
case IO_NORMAL:
|
||||
vio->vui_iter = args->u.normal.via_iter;
|
||||
vio->vui_iocb = args->u.normal.via_iocb;
|
||||
/*
|
||||
* Direct IO reads must also take range lock,
|
||||
* or multiple reads will try to work on the same pages
|
||||
* See LU-6227 for details.
|
||||
*/
|
||||
if (((iot == CIT_WRITE) ||
|
||||
(iot == CIT_READ && (file->f_flags & O_DIRECT))) &&
|
||||
!(vio->vui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) {
|
||||
CDEBUG(D_VFSTRACE, "Range lock [%llu, %llu]\n",
|
||||
range.rl_node.in_extent.start,
|
||||
range.rl_node.in_extent.end);
|
||||
result = range_lock(&lli->lli_write_tree,
|
||||
&range);
|
||||
if (result < 0)
|
||||
goto out;
|
||||
|
||||
range_locked = true;
|
||||
}
|
||||
down_read(&lli->lli_trunc_sem);
|
||||
break;
|
||||
case IO_SPLICE:
|
||||
vio->u.splice.vui_pipe = args->u.splice.via_pipe;
|
||||
vio->u.splice.vui_flags = args->u.splice.via_flags;
|
||||
break;
|
||||
default:
|
||||
CERROR("Unknown IO type - %u\n", vio->vui_io_subtype);
|
||||
LBUG();
|
||||
range_locked = true;
|
||||
}
|
||||
down_read(&lli->lli_trunc_sem);
|
||||
ll_cl_add(file, env, io);
|
||||
result = cl_io_loop(env, io);
|
||||
ll_cl_remove(file, env);
|
||||
if (args->via_io_subtype == IO_NORMAL)
|
||||
up_read(&lli->lli_trunc_sem);
|
||||
up_read(&lli->lli_trunc_sem);
|
||||
if (range_locked) {
|
||||
CDEBUG(D_VFSTRACE, "Range unlock [%llu, %llu]\n",
|
||||
range.rl_node.in_extent.start,
|
||||
@@ -1235,7 +1221,7 @@ static ssize_t ll_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
|
||||
if (IS_ERR(env))
|
||||
return PTR_ERR(env);
|
||||
|
||||
args = ll_env_args(env, IO_NORMAL);
|
||||
args = ll_env_args(env);
|
||||
args->u.normal.via_iter = to;
|
||||
args->u.normal.via_iocb = iocb;
|
||||
|
||||
@@ -1259,7 +1245,7 @@ static ssize_t ll_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
||||
if (IS_ERR(env))
|
||||
return PTR_ERR(env);
|
||||
|
||||
args = ll_env_args(env, IO_NORMAL);
|
||||
args = ll_env_args(env);
|
||||
args->u.normal.via_iter = from;
|
||||
args->u.normal.via_iocb = iocb;
|
||||
|
||||
@@ -1269,31 +1255,6 @@ static ssize_t ll_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send file content (through pagecache) somewhere with helper
|
||||
*/
|
||||
static ssize_t ll_file_splice_read(struct file *in_file, loff_t *ppos,
|
||||
struct pipe_inode_info *pipe, size_t count,
|
||||
unsigned int flags)
|
||||
{
|
||||
struct lu_env *env;
|
||||
struct vvp_io_args *args;
|
||||
ssize_t result;
|
||||
int refcheck;
|
||||
|
||||
env = cl_env_get(&refcheck);
|
||||
if (IS_ERR(env))
|
||||
return PTR_ERR(env);
|
||||
|
||||
args = ll_env_args(env, IO_SPLICE);
|
||||
args->u.splice.via_pipe = pipe;
|
||||
args->u.splice.via_flags = flags;
|
||||
|
||||
result = ll_file_io_generic(env, args, in_file, CIT_READ, ppos, count);
|
||||
cl_env_put(env, &refcheck);
|
||||
return result;
|
||||
}
|
||||
|
||||
int ll_lov_setstripe_ea_info(struct inode *inode, struct dentry *dentry,
|
||||
__u64 flags, struct lov_user_md *lum,
|
||||
int lum_size)
|
||||
@@ -3267,7 +3228,7 @@ struct file_operations ll_file_operations = {
|
||||
.release = ll_file_release,
|
||||
.mmap = ll_file_mmap,
|
||||
.llseek = ll_file_seek,
|
||||
.splice_read = ll_file_splice_read,
|
||||
.splice_read = generic_file_splice_read,
|
||||
.fsync = ll_fsync,
|
||||
.flush = ll_flush
|
||||
};
|
||||
@@ -3280,7 +3241,7 @@ struct file_operations ll_file_operations_flock = {
|
||||
.release = ll_file_release,
|
||||
.mmap = ll_file_mmap,
|
||||
.llseek = ll_file_seek,
|
||||
.splice_read = ll_file_splice_read,
|
||||
.splice_read = generic_file_splice_read,
|
||||
.fsync = ll_fsync,
|
||||
.flush = ll_flush,
|
||||
.flock = ll_file_flock,
|
||||
@@ -3296,7 +3257,7 @@ struct file_operations ll_file_operations_noflock = {
|
||||
.release = ll_file_release,
|
||||
.mmap = ll_file_mmap,
|
||||
.llseek = ll_file_seek,
|
||||
.splice_read = ll_file_splice_read,
|
||||
.splice_read = generic_file_splice_read,
|
||||
.fsync = ll_fsync,
|
||||
.flush = ll_flush,
|
||||
.flock = ll_file_noflock,
|
||||
|
||||
@@ -908,17 +908,11 @@ void vvp_write_complete(struct vvp_object *club, struct vvp_page *page);
|
||||
*/
|
||||
struct vvp_io_args {
|
||||
/** normal/splice */
|
||||
enum vvp_io_subtype via_io_subtype;
|
||||
|
||||
union {
|
||||
struct {
|
||||
struct kiocb *via_iocb;
|
||||
struct iov_iter *via_iter;
|
||||
} normal;
|
||||
struct {
|
||||
struct pipe_inode_info *via_pipe;
|
||||
unsigned int via_flags;
|
||||
} splice;
|
||||
} u;
|
||||
};
|
||||
|
||||
@@ -946,14 +940,9 @@ static inline struct ll_thread_info *ll_env_info(const struct lu_env *env)
|
||||
return lti;
|
||||
}
|
||||
|
||||
static inline struct vvp_io_args *ll_env_args(const struct lu_env *env,
|
||||
enum vvp_io_subtype type)
|
||||
static inline struct vvp_io_args *ll_env_args(const struct lu_env *env)
|
||||
{
|
||||
struct vvp_io_args *via = &ll_env_info(env)->lti_args;
|
||||
|
||||
via->via_io_subtype = type;
|
||||
|
||||
return via;
|
||||
return &ll_env_info(env)->lti_args;
|
||||
}
|
||||
|
||||
void ll_queue_done_writing(struct inode *inode, unsigned long flags);
|
||||
|
||||
@@ -49,14 +49,6 @@ struct obd_device;
|
||||
struct obd_export;
|
||||
struct page;
|
||||
|
||||
/* specific architecture can implement only part of this list */
|
||||
enum vvp_io_subtype {
|
||||
/** normal IO */
|
||||
IO_NORMAL,
|
||||
/** io started from splice_{read|write} */
|
||||
IO_SPLICE
|
||||
};
|
||||
|
||||
/**
|
||||
* IO state private to IO state private to VVP layer.
|
||||
*/
|
||||
@@ -98,10 +90,6 @@ struct vvp_io {
|
||||
*/
|
||||
bool ft_flags_valid;
|
||||
} fault;
|
||||
struct {
|
||||
struct pipe_inode_info *vui_pipe;
|
||||
unsigned int vui_flags;
|
||||
} splice;
|
||||
struct {
|
||||
struct cl_page_list vui_queue;
|
||||
unsigned long vui_written;
|
||||
@@ -110,8 +98,6 @@ struct vvp_io {
|
||||
} write;
|
||||
} u;
|
||||
|
||||
enum vvp_io_subtype vui_io_subtype;
|
||||
|
||||
/**
|
||||
* Layout version when this IO is initialized
|
||||
*/
|
||||
|
||||
@@ -53,18 +53,6 @@ static struct vvp_io *cl2vvp_io(const struct lu_env *env,
|
||||
return vio;
|
||||
}
|
||||
|
||||
/**
|
||||
* True, if \a io is a normal io, False for splice_{read,write}
|
||||
*/
|
||||
static int cl_is_normalio(const struct lu_env *env, const struct cl_io *io)
|
||||
{
|
||||
struct vvp_io *vio = vvp_env_io(env);
|
||||
|
||||
LASSERT(io->ci_type == CIT_READ || io->ci_type == CIT_WRITE);
|
||||
|
||||
return vio->vui_io_subtype == IO_NORMAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* For swapping layout. The file's layout may have changed.
|
||||
* To avoid populating pages to a wrong stripe, we have to verify the
|
||||
@@ -390,9 +378,6 @@ static int vvp_mmap_locks(const struct lu_env *env,
|
||||
|
||||
LASSERT(io->ci_type == CIT_READ || io->ci_type == CIT_WRITE);
|
||||
|
||||
if (!cl_is_normalio(env, io))
|
||||
return 0;
|
||||
|
||||
if (!vio->vui_iter) /* nfs or loop back device write */
|
||||
return 0;
|
||||
|
||||
@@ -461,15 +446,10 @@ static void vvp_io_advance(const struct lu_env *env,
|
||||
const struct cl_io_slice *ios,
|
||||
size_t nob)
|
||||
{
|
||||
struct vvp_io *vio = cl2vvp_io(env, ios);
|
||||
struct cl_io *io = ios->cis_io;
|
||||
struct cl_object *obj = ios->cis_io->ci_obj;
|
||||
|
||||
struct vvp_io *vio = cl2vvp_io(env, ios);
|
||||
CLOBINVRNT(env, obj, vvp_object_invariant(obj));
|
||||
|
||||
if (!cl_is_normalio(env, io))
|
||||
return;
|
||||
|
||||
iov_iter_reexpand(vio->vui_iter, vio->vui_tot_count -= nob);
|
||||
}
|
||||
|
||||
@@ -478,7 +458,7 @@ static void vvp_io_update_iov(const struct lu_env *env,
|
||||
{
|
||||
size_t size = io->u.ci_rw.crw_count;
|
||||
|
||||
if (!cl_is_normalio(env, io) || !vio->vui_iter)
|
||||
if (!vio->vui_iter)
|
||||
return;
|
||||
|
||||
iov_iter_truncate(vio->vui_iter, size);
|
||||
@@ -715,25 +695,8 @@ static int vvp_io_read_start(const struct lu_env *env,
|
||||
|
||||
/* BUG: 5972 */
|
||||
file_accessed(file);
|
||||
switch (vio->vui_io_subtype) {
|
||||
case IO_NORMAL:
|
||||
LASSERT(vio->vui_iocb->ki_pos == pos);
|
||||
result = generic_file_read_iter(vio->vui_iocb, vio->vui_iter);
|
||||
break;
|
||||
case IO_SPLICE:
|
||||
result = generic_file_splice_read(file, &pos,
|
||||
vio->u.splice.vui_pipe, cnt,
|
||||
vio->u.splice.vui_flags);
|
||||
/* LU-1109: do splice read stripe by stripe otherwise if it
|
||||
* may make nfsd stuck if this read occupied all internal pipe
|
||||
* buffers.
|
||||
*/
|
||||
io->ci_continue = 0;
|
||||
break;
|
||||
default:
|
||||
CERROR("Wrong IO type %u\n", vio->vui_io_subtype);
|
||||
LBUG();
|
||||
}
|
||||
LASSERT(vio->vui_iocb->ki_pos == pos);
|
||||
result = generic_file_read_iter(vio->vui_iocb, vio->vui_iter);
|
||||
|
||||
out:
|
||||
if (result >= 0) {
|
||||
|
||||
+1
-22
@@ -37,27 +37,6 @@ coda_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
|
||||
return vfs_iter_read(cfi->cfi_container, to, &iocb->ki_pos);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
coda_file_splice_read(struct file *coda_file, loff_t *ppos,
|
||||
struct pipe_inode_info *pipe, size_t count,
|
||||
unsigned int flags)
|
||||
{
|
||||
ssize_t (*splice_read)(struct file *, loff_t *,
|
||||
struct pipe_inode_info *, size_t, unsigned int);
|
||||
struct coda_file_info *cfi;
|
||||
struct file *host_file;
|
||||
|
||||
cfi = CODA_FTOC(coda_file);
|
||||
BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
|
||||
host_file = cfi->cfi_container;
|
||||
|
||||
splice_read = host_file->f_op->splice_read;
|
||||
if (!splice_read)
|
||||
splice_read = default_file_splice_read;
|
||||
|
||||
return splice_read(host_file, ppos, pipe, count, flags);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
coda_file_write_iter(struct kiocb *iocb, struct iov_iter *to)
|
||||
{
|
||||
@@ -225,6 +204,6 @@ const struct file_operations coda_file_operations = {
|
||||
.open = coda_open,
|
||||
.release = coda_release,
|
||||
.fsync = coda_fsync,
|
||||
.splice_read = coda_file_splice_read,
|
||||
.splice_read = generic_file_splice_read,
|
||||
};
|
||||
|
||||
|
||||
@@ -246,6 +246,9 @@ static ssize_t dio_complete(struct dio *dio, ssize_t ret, bool is_async)
|
||||
if ((dio->op == REQ_OP_READ) &&
|
||||
((offset + transferred) > dio->i_size))
|
||||
transferred = dio->i_size - offset;
|
||||
/* ignore EFAULT if some IO has been done */
|
||||
if (unlikely(ret == -EFAULT) && transferred)
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
|
||||
+16
-47
@@ -728,7 +728,7 @@ static int fuse_copy_fill(struct fuse_copy_state *cs)
|
||||
struct pipe_buffer *buf = cs->pipebufs;
|
||||
|
||||
if (!cs->write) {
|
||||
err = buf->ops->confirm(cs->pipe, buf);
|
||||
err = pipe_buf_confirm(cs->pipe, buf);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -827,7 +827,7 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep)
|
||||
|
||||
fuse_copy_finish(cs);
|
||||
|
||||
err = buf->ops->confirm(cs->pipe, buf);
|
||||
err = pipe_buf_confirm(cs->pipe, buf);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -840,7 +840,7 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep)
|
||||
if (cs->len != PAGE_SIZE)
|
||||
goto out_fallback;
|
||||
|
||||
if (buf->ops->steal(cs->pipe, buf) != 0)
|
||||
if (pipe_buf_steal(cs->pipe, buf) != 0)
|
||||
goto out_fallback;
|
||||
|
||||
newpage = buf->page;
|
||||
@@ -1341,9 +1341,8 @@ static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos,
|
||||
struct pipe_inode_info *pipe,
|
||||
size_t len, unsigned int flags)
|
||||
{
|
||||
int ret;
|
||||
int total, ret;
|
||||
int page_nr = 0;
|
||||
int do_wakeup = 0;
|
||||
struct pipe_buffer *bufs;
|
||||
struct fuse_copy_state cs;
|
||||
struct fuse_dev *fud = fuse_get_dev(in);
|
||||
@@ -1362,52 +1361,23 @@ static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos,
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = 0;
|
||||
pipe_lock(pipe);
|
||||
|
||||
if (!pipe->readers) {
|
||||
send_sig(SIGPIPE, current, 0);
|
||||
if (!ret)
|
||||
ret = -EPIPE;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (pipe->nrbufs + cs.nr_segs > pipe->buffers) {
|
||||
ret = -EIO;
|
||||
goto out_unlock;
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (page_nr < cs.nr_segs) {
|
||||
int newbuf = (pipe->curbuf + pipe->nrbufs) & (pipe->buffers - 1);
|
||||
struct pipe_buffer *buf = pipe->bufs + newbuf;
|
||||
|
||||
buf->page = bufs[page_nr].page;
|
||||
buf->offset = bufs[page_nr].offset;
|
||||
buf->len = bufs[page_nr].len;
|
||||
for (ret = total = 0; page_nr < cs.nr_segs; total += ret) {
|
||||
/*
|
||||
* Need to be careful about this. Having buf->ops in module
|
||||
* code can Oops if the buffer persists after module unload.
|
||||
*/
|
||||
buf->ops = &nosteal_pipe_buf_ops;
|
||||
|
||||
pipe->nrbufs++;
|
||||
page_nr++;
|
||||
ret += buf->len;
|
||||
|
||||
if (pipe->files)
|
||||
do_wakeup = 1;
|
||||
bufs[page_nr].ops = &nosteal_pipe_buf_ops;
|
||||
ret = add_to_pipe(pipe, &bufs[page_nr++]);
|
||||
if (unlikely(ret < 0))
|
||||
break;
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
pipe_unlock(pipe);
|
||||
|
||||
if (do_wakeup) {
|
||||
smp_mb();
|
||||
if (waitqueue_active(&pipe->wait))
|
||||
wake_up_interruptible(&pipe->wait);
|
||||
kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
|
||||
}
|
||||
|
||||
if (total)
|
||||
ret = total;
|
||||
out:
|
||||
for (; page_nr < cs.nr_segs; page_nr++)
|
||||
put_page(bufs[page_nr].page);
|
||||
@@ -1992,7 +1962,7 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
|
||||
pipe->curbuf = (pipe->curbuf + 1) & (pipe->buffers - 1);
|
||||
pipe->nrbufs--;
|
||||
} else {
|
||||
ibuf->ops->get(pipe, ibuf);
|
||||
pipe_buf_get(pipe, ibuf);
|
||||
*obuf = *ibuf;
|
||||
obuf->flags &= ~PIPE_BUF_FLAG_GIFT;
|
||||
obuf->len = rem;
|
||||
@@ -2014,10 +1984,9 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
|
||||
|
||||
ret = fuse_dev_do_write(fud, &cs, len);
|
||||
|
||||
for (idx = 0; idx < nbuf; idx++) {
|
||||
struct pipe_buffer *buf = &bufs[idx];
|
||||
buf->ops->release(pipe, buf);
|
||||
}
|
||||
for (idx = 0; idx < nbuf; idx++)
|
||||
pipe_buf_release(pipe, &bufs[idx]);
|
||||
|
||||
out:
|
||||
kfree(bufs);
|
||||
return ret;
|
||||
|
||||
+2
-26
@@ -954,30 +954,6 @@ out_uninit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t gfs2_file_splice_read(struct file *in, loff_t *ppos,
|
||||
struct pipe_inode_info *pipe, size_t len,
|
||||
unsigned int flags)
|
||||
{
|
||||
struct inode *inode = in->f_mapping->host;
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
struct gfs2_holder gh;
|
||||
int ret;
|
||||
|
||||
inode_lock(inode);
|
||||
|
||||
ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
|
||||
if (ret) {
|
||||
inode_unlock(inode);
|
||||
return ret;
|
||||
}
|
||||
|
||||
gfs2_glock_dq_uninit(&gh);
|
||||
inode_unlock(inode);
|
||||
|
||||
return generic_file_splice_read(in, ppos, pipe, len, flags);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t gfs2_file_splice_write(struct pipe_inode_info *pipe,
|
||||
struct file *out, loff_t *ppos,
|
||||
size_t len, unsigned int flags)
|
||||
@@ -1140,7 +1116,7 @@ const struct file_operations gfs2_file_fops = {
|
||||
.fsync = gfs2_fsync,
|
||||
.lock = gfs2_lock,
|
||||
.flock = gfs2_flock,
|
||||
.splice_read = gfs2_file_splice_read,
|
||||
.splice_read = generic_file_splice_read,
|
||||
.splice_write = gfs2_file_splice_write,
|
||||
.setlease = simple_nosetlease,
|
||||
.fallocate = gfs2_fallocate,
|
||||
@@ -1168,7 +1144,7 @@ const struct file_operations gfs2_file_fops_nolock = {
|
||||
.open = gfs2_open,
|
||||
.release = gfs2_release,
|
||||
.fsync = gfs2_fsync,
|
||||
.splice_read = gfs2_file_splice_read,
|
||||
.splice_read = generic_file_splice_read,
|
||||
.splice_write = gfs2_file_splice_write,
|
||||
.setlease = generic_setlease,
|
||||
.fallocate = gfs2_fallocate,
|
||||
|
||||
+1
-24
@@ -182,29 +182,6 @@ nfs_file_read(struct kiocb *iocb, struct iov_iter *to)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_file_read);
|
||||
|
||||
ssize_t
|
||||
nfs_file_splice_read(struct file *filp, loff_t *ppos,
|
||||
struct pipe_inode_info *pipe, size_t count,
|
||||
unsigned int flags)
|
||||
{
|
||||
struct inode *inode = file_inode(filp);
|
||||
ssize_t res;
|
||||
|
||||
dprintk("NFS: splice_read(%pD2, %lu@%Lu)\n",
|
||||
filp, (unsigned long) count, (unsigned long long) *ppos);
|
||||
|
||||
nfs_start_io_read(inode);
|
||||
res = nfs_revalidate_mapping(inode, filp->f_mapping);
|
||||
if (!res) {
|
||||
res = generic_file_splice_read(filp, ppos, pipe, count, flags);
|
||||
if (res > 0)
|
||||
nfs_add_stats(inode, NFSIOS_NORMALREADBYTES, res);
|
||||
}
|
||||
nfs_end_io_read(inode);
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_file_splice_read);
|
||||
|
||||
int
|
||||
nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
|
||||
{
|
||||
@@ -871,7 +848,7 @@ const struct file_operations nfs_file_operations = {
|
||||
.fsync = nfs_file_fsync,
|
||||
.lock = nfs_lock,
|
||||
.flock = nfs_flock,
|
||||
.splice_read = nfs_file_splice_read,
|
||||
.splice_read = generic_file_splice_read,
|
||||
.splice_write = iter_file_splice_write,
|
||||
.check_flags = nfs_check_flags,
|
||||
.setlease = simple_nosetlease,
|
||||
|
||||
@@ -365,8 +365,6 @@ int nfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *)
|
||||
int nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync);
|
||||
loff_t nfs_file_llseek(struct file *, loff_t, int);
|
||||
ssize_t nfs_file_read(struct kiocb *, struct iov_iter *);
|
||||
ssize_t nfs_file_splice_read(struct file *, loff_t *, struct pipe_inode_info *,
|
||||
size_t, unsigned int);
|
||||
int nfs_file_mmap(struct file *, struct vm_area_struct *);
|
||||
ssize_t nfs_file_write(struct kiocb *, struct iov_iter *);
|
||||
int nfs_file_release(struct inode *, struct file *);
|
||||
|
||||
+1
-1
@@ -248,7 +248,7 @@ const struct file_operations nfs4_file_operations = {
|
||||
.fsync = nfs_file_fsync,
|
||||
.lock = nfs_lock,
|
||||
.flock = nfs_flock,
|
||||
.splice_read = nfs_file_splice_read,
|
||||
.splice_read = generic_file_splice_read,
|
||||
.splice_write = iter_file_splice_write,
|
||||
.check_flags = nfs_check_flags,
|
||||
.setlease = simple_nosetlease,
|
||||
|
||||
+2
-32
@@ -2321,36 +2321,6 @@ out_mutex:
|
||||
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)
|
||||
{
|
||||
int ret = 0, lock_level = 0;
|
||||
struct inode *inode = file_inode(in);
|
||||
|
||||
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, len);
|
||||
|
||||
/*
|
||||
* See the comment in ocfs2_file_read_iter()
|
||||
*/
|
||||
ret = ocfs2_inode_lock_atime(inode, in->f_path.mnt, &lock_level);
|
||||
if (ret < 0) {
|
||||
mlog_errno(ret);
|
||||
goto bail;
|
||||
}
|
||||
ocfs2_inode_unlock(inode, lock_level);
|
||||
|
||||
ret = generic_file_splice_read(in, ppos, pipe, len, flags);
|
||||
|
||||
bail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t ocfs2_file_read_iter(struct kiocb *iocb,
|
||||
struct iov_iter *to)
|
||||
{
|
||||
@@ -2509,7 +2479,7 @@ const struct file_operations ocfs2_fops = {
|
||||
#endif
|
||||
.lock = ocfs2_lock,
|
||||
.flock = ocfs2_flock,
|
||||
.splice_read = ocfs2_file_splice_read,
|
||||
.splice_read = generic_file_splice_read,
|
||||
.splice_write = iter_file_splice_write,
|
||||
.fallocate = ocfs2_fallocate,
|
||||
};
|
||||
@@ -2554,7 +2524,7 @@ const struct file_operations ocfs2_fops_no_plocks = {
|
||||
.compat_ioctl = ocfs2_compat_ioctl,
|
||||
#endif
|
||||
.flock = ocfs2_flock,
|
||||
.splice_read = ocfs2_file_splice_read,
|
||||
.splice_read = generic_file_splice_read,
|
||||
.splice_write = iter_file_splice_write,
|
||||
.fallocate = ocfs2_fallocate,
|
||||
};
|
||||
|
||||
@@ -1314,8 +1314,6 @@ DEFINE_OCFS2_FILE_OPS(ocfs2_file_aio_write);
|
||||
|
||||
DEFINE_OCFS2_FILE_OPS(ocfs2_file_splice_write);
|
||||
|
||||
DEFINE_OCFS2_FILE_OPS(ocfs2_file_splice_read);
|
||||
|
||||
DEFINE_OCFS2_FILE_OPS(ocfs2_file_aio_read);
|
||||
|
||||
DEFINE_OCFS2_ULL_ULL_ULL_EVENT(ocfs2_truncate_file);
|
||||
|
||||
@@ -267,7 +267,6 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
|
||||
if (bufs) {
|
||||
int curbuf = pipe->curbuf;
|
||||
struct pipe_buffer *buf = pipe->bufs + curbuf;
|
||||
const struct pipe_buf_operations *ops = buf->ops;
|
||||
size_t chars = buf->len;
|
||||
size_t written;
|
||||
int error;
|
||||
@@ -275,7 +274,7 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
|
||||
if (chars > total_len)
|
||||
chars = total_len;
|
||||
|
||||
error = ops->confirm(pipe, buf);
|
||||
error = pipe_buf_confirm(pipe, buf);
|
||||
if (error) {
|
||||
if (!ret)
|
||||
ret = error;
|
||||
@@ -299,8 +298,7 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
|
||||
}
|
||||
|
||||
if (!buf->len) {
|
||||
buf->ops = NULL;
|
||||
ops->release(pipe, buf);
|
||||
pipe_buf_release(pipe, buf);
|
||||
curbuf = (curbuf + 1) & (pipe->buffers - 1);
|
||||
pipe->curbuf = curbuf;
|
||||
pipe->nrbufs = --bufs;
|
||||
@@ -383,11 +381,10 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from)
|
||||
int lastbuf = (pipe->curbuf + pipe->nrbufs - 1) &
|
||||
(pipe->buffers - 1);
|
||||
struct pipe_buffer *buf = pipe->bufs + lastbuf;
|
||||
const struct pipe_buf_operations *ops = buf->ops;
|
||||
int offset = buf->offset + buf->len;
|
||||
|
||||
if (ops->can_merge && offset + chars <= PAGE_SIZE) {
|
||||
ret = ops->confirm(pipe, buf);
|
||||
if (buf->ops->can_merge && offset + chars <= PAGE_SIZE) {
|
||||
ret = pipe_buf_confirm(pipe, buf);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -664,7 +661,7 @@ void free_pipe_info(struct pipe_inode_info *pipe)
|
||||
for (i = 0; i < pipe->buffers; i++) {
|
||||
struct pipe_buffer *buf = pipe->bufs + i;
|
||||
if (buf->ops)
|
||||
buf->ops->release(pipe, buf);
|
||||
pipe_buf_release(pipe, buf);
|
||||
}
|
||||
if (pipe->tmp_page)
|
||||
__free_page(pipe->tmp_page);
|
||||
|
||||
+200
-487
File diff suppressed because it is too large
Load Diff
+1
-40
@@ -393,45 +393,6 @@ xfs_file_read_iter(
|
||||
return ret;
|
||||
}
|
||||
|
||||
STATIC ssize_t
|
||||
xfs_file_splice_read(
|
||||
struct file *infilp,
|
||||
loff_t *ppos,
|
||||
struct pipe_inode_info *pipe,
|
||||
size_t count,
|
||||
unsigned int flags)
|
||||
{
|
||||
struct xfs_inode *ip = XFS_I(infilp->f_mapping->host);
|
||||
ssize_t ret;
|
||||
|
||||
XFS_STATS_INC(ip->i_mount, xs_read_calls);
|
||||
|
||||
if (XFS_FORCED_SHUTDOWN(ip->i_mount))
|
||||
return -EIO;
|
||||
|
||||
trace_xfs_file_splice_read(ip, count, *ppos);
|
||||
|
||||
/*
|
||||
* DAX inodes cannot ues the page cache for splice, so we have to push
|
||||
* them through the VFS IO path. This means it goes through
|
||||
* ->read_iter, which for us takes the XFS_IOLOCK_SHARED. Hence we
|
||||
* cannot lock the splice operation at this level for DAX inodes.
|
||||
*/
|
||||
if (IS_DAX(VFS_I(ip))) {
|
||||
ret = default_file_splice_read(infilp, ppos, pipe, count,
|
||||
flags);
|
||||
goto out;
|
||||
}
|
||||
|
||||
xfs_rw_ilock(ip, XFS_IOLOCK_SHARED);
|
||||
ret = generic_file_splice_read(infilp, ppos, pipe, count, flags);
|
||||
xfs_rw_iunlock(ip, XFS_IOLOCK_SHARED);
|
||||
out:
|
||||
if (ret > 0)
|
||||
XFS_STATS_ADD(ip->i_mount, xs_read_bytes, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Zero any on disk space between the current EOF and the new, larger EOF.
|
||||
*
|
||||
@@ -1608,7 +1569,7 @@ const struct file_operations xfs_file_operations = {
|
||||
.llseek = xfs_file_llseek,
|
||||
.read_iter = xfs_file_read_iter,
|
||||
.write_iter = xfs_file_write_iter,
|
||||
.splice_read = xfs_file_splice_read,
|
||||
.splice_read = generic_file_splice_read,
|
||||
.splice_write = iter_file_splice_write,
|
||||
.unlocked_ioctl = xfs_file_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
||||
@@ -1170,7 +1170,6 @@ DEFINE_RW_EVENT(xfs_file_dax_read);
|
||||
DEFINE_RW_EVENT(xfs_file_buffered_write);
|
||||
DEFINE_RW_EVENT(xfs_file_direct_write);
|
||||
DEFINE_RW_EVENT(xfs_file_dax_write);
|
||||
DEFINE_RW_EVENT(xfs_file_splice_read);
|
||||
|
||||
DECLARE_EVENT_CLASS(xfs_page_class,
|
||||
TP_PROTO(struct inode *inode, struct page *page, unsigned long off,
|
||||
|
||||
@@ -2794,8 +2794,6 @@ extern void block_sync_page(struct page *page);
|
||||
/* fs/splice.c */
|
||||
extern ssize_t generic_file_splice_read(struct file *, loff_t *,
|
||||
struct pipe_inode_info *, size_t, unsigned int);
|
||||
extern ssize_t default_file_splice_read(struct file *, loff_t *,
|
||||
struct pipe_inode_info *, size_t, unsigned int);
|
||||
extern ssize_t iter_file_splice_write(struct pipe_inode_info *,
|
||||
struct file *, loff_t *, size_t, unsigned int);
|
||||
extern ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe,
|
||||
|
||||
@@ -66,15 +66,10 @@ struct pipe_inode_info {
|
||||
*
|
||||
* ->confirm()
|
||||
* ->steal()
|
||||
* ...
|
||||
* ->map()
|
||||
* ...
|
||||
* ->unmap()
|
||||
*
|
||||
* That is, ->map() must be called on a confirmed buffer,
|
||||
* same goes for ->steal(). See below for the meaning of each
|
||||
* operation. Also see kerneldoc in fs/pipe.c for the pipe
|
||||
* and generic variants of these hooks.
|
||||
* That is, ->steal() must be called on a confirmed buffer.
|
||||
* See below for the meaning of each operation. Also see kerneldoc
|
||||
* in fs/pipe.c for the pipe and generic variants of these hooks.
|
||||
*/
|
||||
struct pipe_buf_operations {
|
||||
/*
|
||||
@@ -115,6 +110,53 @@ struct pipe_buf_operations {
|
||||
void (*get)(struct pipe_inode_info *, struct pipe_buffer *);
|
||||
};
|
||||
|
||||
/**
|
||||
* pipe_buf_get - get a reference to a pipe_buffer
|
||||
* @pipe: the pipe that the buffer belongs to
|
||||
* @buf: the buffer to get a reference to
|
||||
*/
|
||||
static inline void pipe_buf_get(struct pipe_inode_info *pipe,
|
||||
struct pipe_buffer *buf)
|
||||
{
|
||||
buf->ops->get(pipe, buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* pipe_buf_release - put a reference to a pipe_buffer
|
||||
* @pipe: the pipe that the buffer belongs to
|
||||
* @buf: the buffer to put a reference to
|
||||
*/
|
||||
static inline void pipe_buf_release(struct pipe_inode_info *pipe,
|
||||
struct pipe_buffer *buf)
|
||||
{
|
||||
const struct pipe_buf_operations *ops = buf->ops;
|
||||
|
||||
buf->ops = NULL;
|
||||
ops->release(pipe, buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* pipe_buf_confirm - verify contents of the pipe buffer
|
||||
* @pipe: the pipe that the buffer belongs to
|
||||
* @buf: the buffer to confirm
|
||||
*/
|
||||
static inline int pipe_buf_confirm(struct pipe_inode_info *pipe,
|
||||
struct pipe_buffer *buf)
|
||||
{
|
||||
return buf->ops->confirm(pipe, buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* pipe_buf_steal - attempt to take ownership of a pipe_buffer
|
||||
* @pipe: the pipe that the buffer belongs to
|
||||
* @buf: the buffer to attempt to steal
|
||||
*/
|
||||
static inline int pipe_buf_steal(struct pipe_inode_info *pipe,
|
||||
struct pipe_buffer *buf)
|
||||
{
|
||||
return buf->ops->steal(pipe, buf);
|
||||
}
|
||||
|
||||
/* Differs from PIPE_BUF in that PIPE_SIZE is the length of the actual
|
||||
memory allocation, whereas PIPE_BUF makes atomicity guarantees. */
|
||||
#define PIPE_SIZE PAGE_SIZE
|
||||
@@ -129,7 +171,6 @@ extern unsigned long pipe_user_pages_hard;
|
||||
extern unsigned long pipe_user_pages_soft;
|
||||
int pipe_proc_fn(struct ctl_table *, int, void __user *, size_t *, loff_t *);
|
||||
|
||||
|
||||
/* Drop the inode semaphore and wait for a pipe event, atomically */
|
||||
void pipe_wait(struct pipe_inode_info *pipe);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user