[pnfs] [PATCH 07/11] pnfs: pnfs_write_end

Fredric Isaman iisaman at citi.umich.edu
Mon Apr 14 10:00:45 EDT 2008



On Sun, 13 Apr 2008, Benny Halevy wrote:

> On Apr. 10, 2008, 17:05 +0300, Fred Isaman <iisaman at citi.umich.edu> wrote:
>> Add hooks in the nfs_write_end path, giving a driver the potential for
>> post-copy manipulation of the page.
>>
>> Signed-off-by: Fred Isaman <iisaman at citi.umich.edu>
>> Signed-off-by: Benny Halevy <bhalevy at panasas.com>
>> ---
>>  fs/nfs/file.c             |    4 ++++
>>  fs/nfs/pnfs.c             |   16 ++++++++++++++++
>>  fs/nfs/pnfs.h             |   24 ++++++++++++++++++++++++
>>  fs/nfs/write.c            |    2 +-
>>  include/linux/nfs4_pnfs.h |    3 +++
>>  5 files changed, 48 insertions(+), 1 deletions(-)
>>
>> diff --git a/fs/nfs/file.c b/fs/nfs/file.c
>> index aa0f37d..0ac2406 100644
>> --- a/fs/nfs/file.c
>> +++ b/fs/nfs/file.c
>> @@ -371,10 +371,14 @@ static int nfs_write_end(struct file *file, struct address_space *mapping,
>>  	unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
>>  	int status;
>>
>> +	status = pnfs_write_end(file, page, pos, len, copied, fsdata);
>> +	if (status)
>> +		goto out;
>>  	lock_kernel();
>>  	status = nfs_updatepage(file, page, offset, copied, fsdata);
>>  	unlock_kernel();
>>
>> + out:
>>  	unlock_page(page);
>>  	page_cache_release(page);
>>  	pnfs_write_end_cleanup(fsdata);
>> diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
>> index 2666100..a0b80c2 100644
>> --- a/fs/nfs/pnfs.c
>> +++ b/fs/nfs/pnfs.c
>> @@ -1594,6 +1594,22 @@ int _pnfs_write_begin(struct inode *inode, struct nfs_server *nfss,
>>  	return status;
>>  }
>>
>> +/* Return 0 on succes, negative on failure */
>> +/* CAREFUL - what happens if copied < len??? */
>> +int _pnfs_write_end(struct inode *inode, struct nfs_server *nfss,
>
> ditto nfss.
>

OK


>> +		    struct page *page, loff_t pos, unsigned len,
>> +		    unsigned copied, struct pnfs_fsdata *fsdata)
>> +{
>> +	struct pnfs_layout_segment *lseg;
>> +	int status;
>> +
>> +	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 e8361cd..10a921f 100644
>> --- a/fs/nfs/pnfs.h
>> +++ b/fs/nfs/pnfs.h
>> @@ -63,6 +63,9 @@ void pnfs_layout_release(struct pnfs_layout_type *);
>>  int _pnfs_write_begin(struct inode *inode, struct nfs_server *nfss,
>>  		      struct page *page, loff_t pos, unsigned len,
>>  		      unsigned flags, struct pnfs_fsdata **fsdata);
>> +int _pnfs_write_end(struct inode *inode, struct nfs_server *nfss,
>> +		    struct page *page, loff_t pos, unsigned len,
>> +		    unsigned copied, struct pnfs_fsdata *fsdata);
>>  int _pnfs_do_flush(struct inode *inode, struct nfs_server *nfss,
>>  		   struct nfs_page *req, struct pnfs_fsdata *fsdata);
>>  void _pnfs_modify_new_write_request(struct nfs_server *nfss,
>> @@ -144,6 +147,20 @@ static inline int pnfs_do_flush(struct nfs_page *req, void *fsdata)
>>  		return 0;
>>  }
>>
>> +static inline 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);
>> +
>> +	if (PNFS_EXISTS_LDIO_OP(nfss, write_end))
>> +		return _pnfs_write_end(inode, nfss, page, pos, len, copied,
>> +				       fsdata);
>> +	else
>> +		return 0;
>> +}
>> +
>>  static inline void pnfs_write_end_cleanup(void *fsdata)
>>  {
>>  	pnfs_free_fsdata((struct pnfs_fsdata *) fsdata);
>> @@ -190,6 +207,13 @@ static inline int pnfs_write_begin(struct file *filp, struct page *page,
>>  	return 0;
>>  }
>>
>> +static inline int pnfs_write_end(struct file *filp, struct page *page,
>> +				 loff_t pos, unsigned len, unsigned copied,
>> +				 void *fsdata)
>> +{
>> +	return 0;
>> +}
>> +
>>  static inline void pnfs_write_end_cleanup(void *fsdata)
>>  {
>>  }
>> diff --git a/fs/nfs/write.c b/fs/nfs/write.c
>> index 5cdd1ee..05d16a9 100644
>> --- a/fs/nfs/write.c
>> +++ b/fs/nfs/write.c
>> @@ -657,7 +657,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)
>
> Does this really belong in this patch or in patch 3, pnfs_write_begin.
> Even better, looks like pnfs_do_flush can be coded in a patch of its own, no?
>

It definitely needs to be in patch 3 or before (it needs to be called in 
nfs_write_begin via flush_incompatible).  However, a seperate patch before 
write_begin is reasonable.

Fred

>>  	    || offset > rqend || end < req->wb_offset) {
>>  		nfs_clear_page_tag_locked(req);
>>  		return ERR_PTR(-EBUSY);
>> diff --git a/include/linux/nfs4_pnfs.h b/include/linux/nfs4_pnfs.h
>> index 8881739..d9a231f 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);
>>  	void (*new_request)(struct pnfs_layout_segment *lseg,
>>  			    struct nfs_page *req, loff_t pos, unsigned count,
>>  			    struct pnfs_fsdata *fsdata);
>
>


More information about the pNFS mailing list