Re: [PATCH ver4] exofs: New truncate sequence

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 06/09/2010 02:10 PM, Boaz Harrosh wrote:
> 
> These changes are crafted based on the similar
> conversion done to ext2 by Nick Piggin.
> 
> * Remove the deprecated ->truncate vector. Let exofs_setattr
>   take care of on-disk size updates.
> * Call truncate_pagecache on the unused pages if
>   write_begin/end fails.
> * Cleanup exofs_delete_inode that did stupid inode
>   writes and updates on an inode that will be
>   removed.
> * And finally get rid of exofs_get_block. We never
>   had any blocks it was all for calling nobh_truncate_page.
>   nobh_truncate_page is not actually needed in exofs since
>   the last page is complete and gone, just like all the other
>   pages. There is no partial blocks in exofs.
> 
> I've tested with this patch, and there are no apparent
> failures, so far.
> 
> CC: Nick Piggin <npiggin@xxxxxxx>
> CC: Christoph Hellwig <hch@xxxxxx>
> Signed-off-by: Boaz Harrosh <bharrosh@xxxxxxxxxxx>

Al hi.

Please take this through your tree. And/or tell me if you need it
reorder with your ->evict patches.

Thanks
Boaz

> ---
>  fs/exofs/exofs.h |    1 -
>  fs/exofs/file.c  |    1 -
>  fs/exofs/inode.c |  114 ++++++++++++++++++++----------------------------------
>  3 files changed, 42 insertions(+), 74 deletions(-)
> 
> diff --git a/fs/exofs/exofs.h b/fs/exofs/exofs.h
> index 22721b2..0706ce9 100644
> --- a/fs/exofs/exofs.h
> +++ b/fs/exofs/exofs.h
> @@ -256,7 +256,6 @@ static inline int exofs_oi_read(struct exofs_i_info *oi,
>  }
>  
>  /* inode.c               */
> -void exofs_truncate(struct inode *inode);
>  int exofs_setattr(struct dentry *, struct iattr *);
>  int exofs_write_begin(struct file *file, struct address_space *mapping,
>  		loff_t pos, unsigned len, unsigned flags,
> diff --git a/fs/exofs/file.c b/fs/exofs/file.c
> index fef6899..f9bfe2b 100644
> --- a/fs/exofs/file.c
> +++ b/fs/exofs/file.c
> @@ -86,6 +86,5 @@ const struct file_operations exofs_file_operations = {
>  };
>  
>  const struct inode_operations exofs_file_inode_operations = {
> -	.truncate	= exofs_truncate,
>  	.setattr	= exofs_setattr,
>  };
> diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c
> index 4bfc1f4..5510a5e 100644
> --- a/fs/exofs/inode.c
> +++ b/fs/exofs/inode.c
> @@ -710,7 +710,7 @@ int exofs_write_begin(struct file *file, struct address_space *mapping,
>  					 fsdata);
>  		if (ret) {
>  			EXOFS_DBGMSG("simple_write_begin faild\n");
> -			return ret;
> +			goto out;
>  		}
>  
>  		page = *pagep;
> @@ -725,7 +725,14 @@ int exofs_write_begin(struct file *file, struct address_space *mapping,
>  			EXOFS_DBGMSG("__readpage_filler faild\n");
>  		}
>  	}
> +out:
> +	if (unlikely(ret)) {
> +		struct inode *inode = mapping->host;
> +		loff_t to = pos + len;
>  
> +		if (to > inode->i_size)
> +			truncate_pagecache(inode, to, inode->i_size);
> +	}
>  	return ret;
>  }
>  
> @@ -750,6 +757,10 @@ static int exofs_write_end(struct file *file, struct address_space *mapping,
>  	int ret;
>  
>  	ret = simple_write_end(file, mapping,pos, len, copied, page, fsdata);
> +	if (unlikely(ret && pos + len > inode->i_size))
> +		truncate_pagecache(inode, pos + len, inode->i_size);
> +
> +	/* TODO: once simple_write_end marks inode dirty remove */
>  	if (i_size != inode->i_size)
>  		mark_inode_dirty(inode);
>  	return ret;
> @@ -808,91 +819,53 @@ static inline int exofs_inode_is_fast_symlink(struct inode *inode)
>  	return S_ISLNK(inode->i_mode) && (oi->i_data[0] != 0);
>  }
>  
> -/*
> - * get_block_t - Fill in a buffer_head
> - * An OSD takes care of block allocation so we just fake an allocation by
> - * putting in the inode's sector_t in the buffer_head.
> - * TODO: What about the case of create==0 and @iblock does not exist in the
> - * object?
> - */
> -static int exofs_get_block(struct inode *inode, sector_t iblock,
> -		    struct buffer_head *bh_result, int create)
> -{
> -	map_bh(bh_result, inode->i_sb, iblock);
> -	return 0;
> -}
> -
>  const struct osd_attr g_attr_logical_length = ATTR_DEF(
>  	OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_LOGICAL_LENGTH, 8);
>  
> -static int _do_truncate(struct inode *inode)
> +static int _do_truncate(struct inode *inode, loff_t newsize)
>  {
>  	struct exofs_i_info *oi = exofs_i(inode);
> -	loff_t isize = i_size_read(inode);
>  	int ret;
>  
>  	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
>  
> -	nobh_truncate_page(inode->i_mapping, isize, exofs_get_block);
> +	ret = exofs_oi_truncate(oi, (u64)newsize);
> +	if (likely(!ret))
> +		truncate_setsize(inode, newsize);
>  
> -	ret = exofs_oi_truncate(oi, (u64)isize);
> -	EXOFS_DBGMSG("(0x%lx) size=0x%llx\n", inode->i_ino, isize);
> +	EXOFS_DBGMSG("(0x%lx) size=0x%llx ret=>%d\n",
> +		     inode->i_ino, newsize, ret);
>  	return ret;
>  }
>  
>  /*
> - * Truncate a file to the specified size - all we have to do is set the size
> - * attribute.  We make sure the object exists first.
> - */
> -void exofs_truncate(struct inode *inode)
> -{
> -	struct exofs_i_info *oi = exofs_i(inode);
> -	int ret;
> -
> -	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
> -	     || S_ISLNK(inode->i_mode)))
> -		return;
> -	if (exofs_inode_is_fast_symlink(inode))
> -		return;
> -	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
> -		return;
> -
> -	/* if we are about to truncate an object, and it hasn't been
> -	 * created yet, wait
> -	 */
> -	if (unlikely(wait_obj_created(oi)))
> -		goto fail;
> -
> -	ret = _do_truncate(inode);
> -	if (ret)
> -		goto fail;
> -
> -out:
> -	mark_inode_dirty(inode);
> -	return;
> -fail:
> -	make_bad_inode(inode);
> -	goto out;
> -}
> -
> -/*
> - * Set inode attributes - just call generic functions.
> + * Set inode attributes - update size attribute on OSD if needed,
> + *                        otherwise just call generic functions.
>   */
>  int exofs_setattr(struct dentry *dentry, struct iattr *iattr)
>  {
>  	struct inode *inode = dentry->d_inode;
>  	int error;
>  
> +	/* if we are about to modify an object, and it hasn't been
> +	 * created yet, wait
> +	 */
> +	error = wait_obj_created(exofs_i(inode));
> +	if (unlikely(error))
> +		return error;
> +
>  	error = inode_change_ok(inode, iattr);
> -	if (error)
> +	if (unlikely(error))
>  		return error;
>  
>  	if ((iattr->ia_valid & ATTR_SIZE) &&
>  	    iattr->ia_size != i_size_read(inode)) {
> -		int error;
> +		error = inode_newsize_ok(inode, iattr->ia_size);
> +		if (unlikely(error))
> +			return error;
>  
> -		error = vmtruncate(inode, iattr->ia_size);
> -		if (error)
> +		error = _do_truncate(inode, iattr->ia_size);
> +		if (unlikely(error))
>  			return error;
>  	}
>  
> @@ -1345,28 +1318,25 @@ void exofs_delete_inode(struct inode *inode)
>  
>  	truncate_inode_pages(&inode->i_data, 0);
>  
> +	/* TODO: should do better here */
>  	if (is_bad_inode(inode))
>  		goto no_delete;
>  
> -	mark_inode_dirty(inode);
> -	exofs_update_inode(inode, inode_needs_sync(inode));
> -
>  	inode->i_size = 0;
> -	if (inode->i_blocks)
> -		exofs_truncate(inode);
> -
>  	clear_inode(inode);
>  
> -	ret = exofs_get_io_state(&sbi->layout, &ios);
> -	if (unlikely(ret)) {
> -		EXOFS_ERR("%s: exofs_get_io_state failed\n", __func__);
> -		return;
> -	}
> -
>  	/* if we are deleting an obj that hasn't been created yet, wait */
>  	if (!obj_created(oi)) {
>  		BUG_ON(!obj_2bcreated(oi));
>  		wait_event(oi->i_wq, obj_created(oi));
> +		/* ignore the error attempt a remove anyway */
> +	}
> +
> +	/* Now Remove the OSD objects */
> +	ret = exofs_get_io_state(&sbi->layout, &ios);
> +	if (unlikely(ret)) {
> +		EXOFS_ERR("%s: exofs_get_io_state failed\n", __func__);
> +		return;
>  	}
>  
>  	ios->obj.id = exofs_oi_objno(oi);

--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux