/** * generic_file_splice_write_nolock - generic_file_splice_write without mutexes * @pipe: pipe info * @out: file to write to * @len: number of bytes to splice * @flags: splice modifier flags * * Will either move or copy pages (determined by @flags options) from * the given pipe inode to the given file. The caller is responsible * for acquiring i_mutex on both inodes. * */ ssize_t generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out, loff_t *ppos, size_t len, unsigned int flags) { struct address_space *mapping = out->f_mapping; struct inode *inode = mapping->host; ssize_t ret; int err; err = remove_suid(out->f_dentry); if (unlikely(err)) return err; ret = __splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); if (ret > 0) { *ppos += ret; /* * If file or inode is SYNC and we actually wrote some data, * sync it. */ if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) { err = generic_osync_inode(inode, mapping, OSYNC_METADATA|OSYNC_DATA); if (err) ret = err; } } return ret; }
/** * generic_file_splice_write_nolock - generic_file_splice_write without mutexes * @pipe: pipe info * @out: file to write to * @len: number of bytes to splice * @flags: splice modifier flags * * Will either move or copy pages (determined by @flags options) from * the given pipe inode to the given file. The caller is responsible * for acquiring i_mutex on both inodes. * */ ssize_t generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out, loff_t *ppos, size_t len, unsigned int flags) { struct address_space *mapping = out->f_mapping; struct inode *inode = mapping->host; ssize_t ret; int err; err = remove_suid(out->f_path.dentry); if (unlikely(err)) return err; ret = __splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); if (ret > 0) { unsigned long nr_pages; *ppos += ret; nr_pages = (ret + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; /* * If file or inode is SYNC and we actually wrote some data, * sync it. */ if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) { err = generic_osync_inode(inode, mapping, OSYNC_METADATA|OSYNC_DATA); if (err) ret = err; } balance_dirty_pages_ratelimited_nr(mapping, nr_pages); }
static ssize_t svfs_file_splice_write(struct pipe_inode_info *pipe, struct file *out, loff_t *ppos, size_t len, unsigned int flags) { struct address_space *mapping; struct inode *inode; struct file *llfs_filp; struct svfs_inode *si; struct splice_desc sd = {0,}; ssize_t ret; svfs_entry(mdc, "pos %lu, len %ld, flags 0x%x\n", (unsigned long)*ppos, (long)len, flags); si = SVFS_I(out->f_dentry->d_inode); if (si->state & SVFS_STATE_DA) { /* create it now */ ASSERT(!(si->state & SVFS_STATE_CONN)); ret = llfs_create(out->f_dentry); if (ret) goto out; } if (!(si->state & SVFS_STATE_CONN)) { /* open it ? */ ret = llfs_lookup(out->f_dentry->d_inode); if (ret) goto out; } llfs_filp = si->llfs_md.llfs_filp; ASSERT(llfs_filp); mapping = llfs_filp->f_mapping; inode = mapping->host; sd.total_len = len; sd.flags = flags; sd.pos = *ppos; sd.u.file = llfs_filp; pipe_lock(pipe); splice_from_pipe_begin(&sd); do { ret = splice_from_pipe_next(pipe, &sd); if (ret <= 0) break; mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD); ret = file_remove_suid(out); if (!ret) ret = splice_from_pipe_feed(pipe, &sd, pipe_to_file); mutex_unlock(&inode->i_mutex); } while (ret > 0); splice_from_pipe_end(pipe, &sd); pipe_unlock(pipe); if (sd.num_spliced) ret = sd.num_spliced; if (ret > 0) { unsigned long nr_pages; *ppos += ret; nr_pages = (ret + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; /* * If file or inode is SYNC and we actually wrote some data, * sync it. */ if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) { int err; mutex_lock(&inode->i_mutex); err = generic_osync_inode(inode, mapping, OSYNC_METADATA|OSYNC_DATA); mutex_unlock(&inode->i_mutex); if (err) ret = err; } balance_dirty_pages_ratelimited_nr(mapping, nr_pages); }
static ssize_t __ocfs2_file_splice_write(struct pipe_inode_info *pipe, struct file *out, loff_t *ppos, size_t len, unsigned int flags) { int ret, err; struct address_space *mapping = out->f_mapping; struct inode *inode = mapping->host; struct splice_desc sd = { .total_len = len, .flags = flags, .pos = *ppos, .u.file = out, }; ret = __splice_from_pipe(pipe, &sd, ocfs2_splice_write_actor); if (ret > 0) { *ppos += ret; if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) { err = generic_osync_inode(inode, mapping, OSYNC_METADATA|OSYNC_DATA); if (err) ret = err; } } return ret; } static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe, struct file *out, loff_t *ppos, size_t len, unsigned int flags) { int ret; struct inode *inode = out->f_path.dentry->d_inode; mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", out, pipe, (unsigned int)len, out->f_path.dentry->d_name.len, out->f_path.dentry->d_name.name); mutex_lock_nested(&inode->i_mutex, I_MUTEX_PARENT); ret = ocfs2_rw_lock(inode, 1); if (ret < 0) { mlog_errno(ret); goto out; } ret = ocfs2_prepare_inode_for_write(out->f_path.dentry, ppos, len, 0, NULL); if (ret < 0) { mlog_errno(ret); goto out_unlock; } if (pipe->inode) mutex_lock_nested(&pipe->inode->i_mutex, I_MUTEX_CHILD); /* ok, we're done with i_size and alloc work */ ret = __ocfs2_file_splice_write(pipe, out, ppos, len, flags); if (pipe->inode) mutex_unlock(&pipe->inode->i_mutex); out_unlock: ocfs2_rw_unlock(inode, 1); out: mutex_unlock(&inode->i_mutex); mlog_exit(ret); return ret; }