Exemplo n.º 1
0
/**
 * 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;
}
Exemplo n.º 2
0
/**
 * 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);
	}
Exemplo n.º 3
0
Arquivo: file.c Projeto: macan/SVFS
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);
    }
Exemplo n.º 4
0
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;
}