Esempio n. 1
0
File: file.c Progetto: 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);
    }
Esempio n. 2
0
/*
 * Almost copy of generic_file_splice_write() (added changed_begin/end,
 * tux3_iattrdirty()).
 */
static ssize_t tux3_file_splice_write(struct pipe_inode_info *pipe,
				      struct file *out, loff_t *ppos,
				      size_t len, unsigned int flags)
{
	if(DEBUG_MODE_K==1)
	{
		printk(KERN_INFO"%25s  %25s  %4d  #in\n",__FILE__,__func__,__LINE__);
	}
	struct address_space *mapping = out->f_mapping;
	struct inode *inode = mapping->host;
	struct sb *sb = tux_sb(inode->i_sb);
	struct splice_desc sd = {
		.total_len = len,
		.flags = flags,
		.pos = *ppos,
		.u.file = out,
	};
	ssize_t ret;

	sb_start_write(inode->i_sb);

	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);
		/* For each ->write_end() calls change_end(). */
		change_begin(sb);
		/* For timestamp. FIXME: convert this to ->update_time
		 * handler? */
		tux3_iattrdirty(inode);
		ret = file_remove_suid(out);
		if (!ret) {
			ret = file_update_time(out);
			if (!ret)
				ret = splice_from_pipe_feed(pipe, &sd,
							    pipe_to_file);
		}
		change_end_if_needed(sb);
		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) {
		int err;

		err = generic_write_sync(out, *ppos, ret);
		if (err)
			ret = err;
		else
			*ppos += ret;
		balance_dirty_pages_ratelimited(mapping);
	}
	sb_end_write(inode->i_sb);

	return ret;
}