示例#1
0
/**
 * v9fs_file_write - write to a file
 * @filp: file pointer to write
 * @data: data buffer to write data from
 * @count: size of buffer
 * @offset: offset at which to write data
 *
 */
static ssize_t
v9fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
{
	struct file *file = iocb->ki_filp;
	ssize_t retval;
	loff_t origin;
	int err = 0;

	retval = generic_write_checks(iocb, from);
	if (retval <= 0)
		return retval;

	origin = iocb->ki_pos;
	retval = p9_client_write(file->private_data, iocb->ki_pos, from, &err);
	if (retval > 0) {
		struct inode *inode = file_inode(file);
		loff_t i_size;
		unsigned long pg_start, pg_end;
		pg_start = origin >> PAGE_SHIFT;
		pg_end = (origin + retval - 1) >> PAGE_SHIFT;
		if (inode->i_mapping && inode->i_mapping->nrpages)
			invalidate_inode_pages2_range(inode->i_mapping,
						      pg_start, pg_end);
		iocb->ki_pos += retval;
		i_size = i_size_read(inode);
		if (iocb->ki_pos > i_size) {
			inode_add_bytes(inode, iocb->ki_pos - i_size);
			i_size_write(inode, iocb->ki_pos);
		}
		return retval;
	}
	return err;
}
示例#2
0
ssize_t
v9fs_file_write_internal(struct inode *inode, struct p9_fid *fid,
			 const char __user *data, size_t count,
			 loff_t *offset, int invalidate)
{
	int n;
	loff_t i_size;
	size_t total = 0;
	loff_t origin = *offset;
	unsigned long pg_start, pg_end;

	p9_debug(P9_DEBUG_VFS, "data %p count %d offset %x\n",
		 data, (int)count, (int)*offset);

	do {
		n = p9_client_write(fid, NULL, data+total, origin+total, count);
		if (n <= 0)
			break;
		count -= n;
		total += n;
	} while (count > 0);

	if (invalidate && (total > 0)) {
		pg_start = origin >> PAGE_CACHE_SHIFT;
		pg_end = (origin + total - 1) >> PAGE_CACHE_SHIFT;
		if (inode->i_mapping && inode->i_mapping->nrpages)
			invalidate_inode_pages2_range(inode->i_mapping,
						      pg_start, pg_end);
		*offset += total;
		i_size = i_size_read(inode);
		if (*offset > i_size) {
			inode_add_bytes(inode, *offset - i_size);
			i_size_write(inode, *offset);
		}
	}
int nilfs_btnode_prepare_change_key(struct address_space *btnc,
				    struct nilfs_btnode_chkey_ctxt *ctxt)
{
	struct buffer_head *obh, *nbh;
	struct inode *inode = NILFS_BTNC_I(btnc);
	__u64 oldkey = ctxt->oldkey, newkey = ctxt->newkey;
	int err;

	if (oldkey == newkey)
		return 0;

	obh = ctxt->bh;
	ctxt->newbh = NULL;

	if (inode->i_blkbits == PAGE_CACHE_SHIFT) {
		lock_page(obh->b_page);
retry:
		err = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM);
		if (err)
			goto failed_unlock;
		
		if (unlikely(oldkey != obh->b_page->index))
			NILFS_PAGE_BUG(obh->b_page,
				       "invalid oldkey %lld (newkey=%lld)",
				       (unsigned long long)oldkey,
				       (unsigned long long)newkey);

		spin_lock_irq(&btnc->tree_lock);
		err = radix_tree_insert(&btnc->page_tree, newkey, obh->b_page);
		spin_unlock_irq(&btnc->tree_lock);
		radix_tree_preload_end();
		if (!err)
			return 0;
		else if (err != -EEXIST)
			goto failed_unlock;

		err = invalidate_inode_pages2_range(btnc, newkey, newkey);
		if (!err)
			goto retry;
		
		unlock_page(obh->b_page);
	}

	nbh = nilfs_btnode_create_block(btnc, newkey);
	if (!nbh)
		return -ENOMEM;

	BUG_ON(nbh == obh);
	ctxt->newbh = nbh;
	return 0;

 failed_unlock:
	unlock_page(obh->b_page);
	return err;
}
示例#4
0
文件: vfs_file.c 项目: asdlei00/Ace-i
static ssize_t
v9fs_file_write(struct file *filp, const char __user * data,
                size_t count, loff_t * offset)
{
    int n, rsize, total = 0;
    struct p9_fid *fid;
    struct p9_client *clnt;
    struct inode *inode = filp->f_path.dentry->d_inode;
    loff_t origin = *offset;
    unsigned long pg_start, pg_end;

    P9_DPRINTK(P9_DEBUG_VFS, "data %p count %d offset %x\n", data,
               (int)count, (int)*offset);

    fid = filp->private_data;
    clnt = fid->clnt;

    rsize = fid->iounit;
    if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
        rsize = clnt->msize - P9_IOHDRSZ;

    do {
        if (count < rsize)
            rsize = count;

        n = p9_client_write(fid, NULL, data+total, origin+total,
                            rsize);
        if (n <= 0)
            break;
        count -= n;
        total += n;
    } while (count > 0);

    if (total > 0) {
        pg_start = origin >> PAGE_CACHE_SHIFT;
        pg_end = (origin + total - 1) >> PAGE_CACHE_SHIFT;
        if (inode->i_mapping && inode->i_mapping->nrpages)
            invalidate_inode_pages2_range(inode->i_mapping,
                                          pg_start, pg_end);
        *offset += total;
        i_size_write(inode, i_size_read(inode) + total);
        inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9;
    }
void nilfs_btnode_delete(struct buffer_head *bh)
{
	struct address_space *mapping;
	struct page *page = bh->b_page;
	pgoff_t index = page_index(page);
	int still_dirty;

	page_cache_get(page);
	lock_page(page);
	wait_on_page_writeback(page);

	nilfs_forget_buffer(bh);
	still_dirty = PageDirty(page);
	mapping = page->mapping;
	unlock_page(page);
	page_cache_release(page);

	if (!still_dirty && mapping)
		invalidate_inode_pages2_range(mapping, index, index);
}
示例#6
0
int fuse_reverse_inval_inode(struct super_block *sb, u64 nodeid,
			     loff_t offset, loff_t len)
{
	struct inode *inode;
	pgoff_t pg_start;
	pgoff_t pg_end;

	inode = ilookup5(sb, nodeid, fuse_inode_eq, &nodeid);
	if (!inode)
		return -ENOENT;

	fuse_invalidate_attr(inode);
	if (offset >= 0) {
		pg_start = offset >> PAGE_CACHE_SHIFT;
		if (len <= 0)
			pg_end = -1;
		else
			pg_end = (offset + len - 1) >> PAGE_CACHE_SHIFT;
		invalidate_inode_pages2_range(inode->i_mapping,
					      pg_start, pg_end);
	}
示例#7
0
/**
 * v9fs_file_write - write to a file
 * @filp: file pointer to write
 * @data: data buffer to write data from
 * @count: size of buffer
 * @offset: offset at which to write data
 *
 */
static ssize_t
v9fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
{
	struct file *file = iocb->ki_filp;
	ssize_t retval = 0;
	loff_t origin = iocb->ki_pos;
	size_t count = iov_iter_count(from);
	int err = 0;

	retval = generic_write_checks(file, &origin, &count, 0);
	if (retval)
		return retval;

	iov_iter_truncate(from, count);

	if (!count)
		return 0;

	retval = p9_client_write(file->private_data, origin, from, &err);
	if (retval > 0) {
		struct inode *inode = file_inode(file);
		loff_t i_size;
		unsigned long pg_start, pg_end;
		pg_start = origin >> PAGE_CACHE_SHIFT;
		pg_end = (origin + retval - 1) >> PAGE_CACHE_SHIFT;
		if (inode->i_mapping && inode->i_mapping->nrpages)
			invalidate_inode_pages2_range(inode->i_mapping,
						      pg_start, pg_end);
		origin += retval;
		i_size = i_size_read(inode);
		iocb->ki_pos = origin;
		if (origin > i_size) {
			inode_add_bytes(inode, origin - i_size);
			i_size_write(inode, origin);
		}
		return retval;
	}
	return err;
}
示例#8
0
/**
 * nilfs_btnode_prepare_change_key
 *  prepare to move contents of the block for old key to one of new key.
 *  the old buffer will not be removed, but might be reused for new buffer.
 *  it might return -ENOMEM because of memory allocation errors,
 *  and might return -EIO because of disk read errors.
 */
int nilfs_btnode_prepare_change_key(struct address_space *btnc,
				    struct nilfs_btnode_chkey_ctxt *ctxt)
{
	struct buffer_head *obh, *nbh;
	struct inode *inode = NILFS_BTNC_I(btnc);
	__u64 oldkey = ctxt->oldkey, newkey = ctxt->newkey;
	int err;

	if (oldkey == newkey)
		return 0;

	obh = ctxt->bh;
	ctxt->newbh = NULL;

	if (inode->i_blkbits == PAGE_CACHE_SHIFT) {
		lock_page(obh->b_page);
		/*
		 * We cannot call radix_tree_preload for the kernels older
		 * than 2.6.23, because it is not exported for modules.
		 */
retry:
		err = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM);
		if (err)
			goto failed_unlock;
		/* BUG_ON(oldkey != obh->b_page->index); */
		if (unlikely(oldkey != obh->b_page->index))
			NILFS_PAGE_BUG(obh->b_page,
				       "invalid oldkey %lld (newkey=%lld)",
				       (unsigned long long)oldkey,
				       (unsigned long long)newkey);

		spin_lock_irq(&btnc->tree_lock);
		err = radix_tree_insert(&btnc->page_tree, newkey, obh->b_page);
		spin_unlock_irq(&btnc->tree_lock);
		/*
		 * Note: page->index will not change to newkey until
		 * nilfs_btnode_commit_change_key() will be called.
		 * To protect the page in intermediate state, the page lock
		 * is held.
		 */
		radix_tree_preload_end();
		if (!err)
			return 0;
		else if (err != -EEXIST)
			goto failed_unlock;

		err = invalidate_inode_pages2_range(btnc, newkey, newkey);
		if (!err)
			goto retry;
		/* fallback to copy mode */
		unlock_page(obh->b_page);
	}

	nbh = nilfs_btnode_create_block(btnc, newkey);
	if (!nbh)
		return -ENOMEM;

	BUG_ON(nbh == obh);
	ctxt->newbh = nbh;
	return 0;

 failed_unlock:
	unlock_page(obh->b_page);
	return err;
}
示例#9
0
/**
 * invalidate_inode_pages2 - remove all pages from an address_space
 * @mapping: the address_space
 *
 * Any pages which are found to be mapped into pagetables are unmapped prior to
 * invalidation.
 *
 * Returns -EBUSY if any pages could not be invalidated.
 */
int invalidate_inode_pages2(struct address_space *mapping)
{
    return invalidate_inode_pages2_range(mapping, 0, -1);
}