[pnfs] [PATCH 25/28] pnfs: pnfs_write_end

Benny Halevy bhalevy at panasas.com
Thu Mar 13 10:24:33 EDT 2008


On Mar. 11, 2008, 21:32 +0200, Fred Isaman <iisaman at citi.umich.edu> wrote:
> Add hooks in the nfs_write_end path, giving a driver the potential to
> post-copy manipulation of page.
> 
> Signed-off-by: Fred Isaman <iisaman at citi.umich.edu>
> ---
>  fs/nfs/file.c             |    7 +++++++
>  fs/nfs/pnfs.c             |   20 ++++++++++++++++++++
>  fs/nfs/pnfs.h             |    2 ++
>  fs/nfs/write.c            |    2 +-
>  include/linux/nfs4_pnfs.h |    3 +++
>  5 files changed, 33 insertions(+), 1 deletions(-)
> 
> diff --git a/fs/nfs/file.c b/fs/nfs/file.c
> index a7c37e4..815cbc9 100644
> --- a/fs/nfs/file.c
> +++ b/fs/nfs/file.c
> @@ -375,10 +375,17 @@ static int nfs_write_end(struct file *file, struct address_space *mapping,
>  	unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
>  	int status;
>  
> +#ifdef CONFIG_PNFS
> +	/* CAREFUL - what happens if copied < len??? */
> +	status = pnfs_write_end(file, page, pos, len, copied, fsdata);

ditto static inline no-op version

> +	if (status)
> +		goto out;
> +#endif
>  	lock_kernel();
>  	status = nfs_updatepage(file, page, offset, copied, fsdata);
>  	unlock_kernel();
>  
> + out:
>  	unlock_page(page);
>  	page_cache_release(page);
>  #ifdef CONFIG_PNFS
> diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
> index 4c4927f..4fa54ed 100644
> --- a/fs/nfs/pnfs.c
> +++ b/fs/nfs/pnfs.c
> @@ -1594,6 +1594,26 @@ int pnfs_write_begin(struct file *filp, struct page *page,
>  	return status;
>  }
>  
> +/* Return 0 on succes, negative on failure */
> +/* CAREFUL - what happens if copied < len??? */
> +int pnfs_write_end(struct file *filp, struct page *page,
> +		   loff_t pos, unsigned len, unsigned copied, void *fsdata)
> +{
> +	struct inode *inode = filp->f_dentry->d_inode;
> +	struct nfs_server *nfss = NFS_SERVER(inode);
> +	struct pnfs_layout_segment *lseg;
> +	int status;
> +
> +	if (!nfss->pnfs_curr_ld || !nfss->pnfs_curr_ld->ld_io_ops ||
> +	    !nfss->pnfs_curr_ld->ld_io_ops->write_begin)

check should be for write_end, not write_begin...

> +		return 0;

ditto move this condition to static inline wrapper.

Thanks!

Benny

> +	lseg = pnfs_find_get_lseg(inode, pos, len, IOMODE_RW);
> +	status = nfss->pnfs_curr_ld->ld_io_ops->write_end(inode, page,
> +						pos, len, copied, fsdata);
> +	put_lseg(lseg);
> +	return status;
> +}
> +
>  /* Given an nfs request, determine if it should be flushed before proceeding.
>   * It should default to returning False, returning True only if there is a
>   * specific reason to flush.
> diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
> index 9824f78..1509fb7 100644
> --- a/fs/nfs/pnfs.h
> +++ b/fs/nfs/pnfs.h
> @@ -31,6 +31,8 @@ int pnfs_use_write(struct inode *inode, ssize_t count);
>  int pnfs_try_to_write_data(struct nfs_write_data *, const struct rpc_call_ops *, int);
>  int pnfs_write_begin(struct file *filp, struct page *page, loff_t pos,
>  		     unsigned len, unsigned flags, void **fsdata);
> +int pnfs_write_end(struct file *filp, struct page *page,
> +		   loff_t pos, unsigned len, unsigned copied, void *fsdata);
>  int pnfs_do_flush(struct nfs_page *req, void *fsdata);
>  int pnfs_try_to_read_data(struct nfs_read_data *data, const struct rpc_call_ops *call_ops);
>  int pnfs_initialize(void);
> diff --git a/fs/nfs/write.c b/fs/nfs/write.c
> index 24bfcb5..575c067 100644
> --- a/fs/nfs/write.c
> +++ b/fs/nfs/write.c
> @@ -656,7 +656,7 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
>  	rqend = req->wb_offset + req->wb_bytes;
>  	if (req->wb_context != ctx
>  	    || req->wb_page != page
> -	    || !nfs_dirty_request(req)
> +	    || !nfs_dirty_request(req) || pnfs_do_flush(req, fsdata)
>  	    || offset > rqend || end < req->wb_offset) {
>  		nfs_unlock_request(req);
>  		return ERR_PTR(-EBUSY);
> diff --git a/include/linux/nfs4_pnfs.h b/include/linux/nfs4_pnfs.h
> index 000e9eb..9ac366f 100644
> --- a/include/linux/nfs4_pnfs.h
> +++ b/include/linux/nfs4_pnfs.h
> @@ -141,6 +141,9 @@ struct layoutdriver_io_operations {
>  	int (*write_begin) (struct pnfs_layout_segment *lseg, struct page *page,
>  			    loff_t pos, unsigned count,
>  			    struct pnfs_fsdata **fsdata);
> +	int (*write_end)(struct inode *inode, struct page *page, loff_t pos,
> +			 unsigned count, unsigned copied,
> +			 struct pnfs_fsdata *fsdata);
>  	/* Hook into nfs_create_request, for setting wb_private */
>  	void (*new_request)(struct pnfs_layout_segment *lseg,
>  			    struct nfs_page *req, loff_t pos, unsigned count,



More information about the pNFS mailing list