[pnfs] [PATCH 19/28] pnfs: pnfs_write_begin
Fredric Isaman
iisaman at citi.umich.edu
Thu Mar 13 14:46:43 EDT 2008
On Thu, 13 Mar 2008, Benny Halevy wrote:
> On Mar. 11, 2008, 21:32 +0200, Fred Isaman <iisaman at citi.umich.edu> wrote:
>> From: Fred <iisaman at citi.umich.edu>
>>
>> Add hooks in the nfs_write_begin path, giving a driver the potential
>> to read in page data around the data that is about to be copied to the page.
>>
>> Signed-off-by: Fred <iisaman at citi.umich.edu>
>> ---
>> fs/nfs/file.c | 20 ++++++++--
>> fs/nfs/pnfs.c | 88 +++++++++++++++++++++++++++++++++++++++++++++
>> fs/nfs/pnfs.h | 10 +++++
>> fs/nfs/write.c | 2 +-
>> include/linux/nfs4_pnfs.h | 15 +++++++-
>> 5 files changed, 129 insertions(+), 6 deletions(-)
>>
>> diff --git a/fs/nfs/file.c b/fs/nfs/file.c
>> index 6f16772..e870982 100644
>> --- a/fs/nfs/file.c
>> +++ b/fs/nfs/file.c
>> @@ -352,10 +352,19 @@ static int nfs_write_begin(struct file *file, struct address_space *mapping,
>> *pagep = page;
>>
>> ret = nfs_flush_incompatible(file, page);
>> - if (ret) {
>> - unlock_page(page);
>> - page_cache_release(page);
>> - }
>> + if (ret)
>> + goto out_err;
>> +#ifdef CONFIG_PNFS
>> + ret = pnfs_write_begin(file, page, pos, len, flags, fsdata);
>> + if (ret)
>> + goto out_err;
>> +#endif /* CONFIG_PNFS */
>> + return 0;
>> +
>> + out_err:
>> + unlock_page(page);
>> + page_cache_release(page);
>> + *pagep = NULL;
>> return ret;
>> }
>>
>> @@ -372,6 +381,9 @@ static int nfs_write_end(struct file *file, struct address_space *mapping,
>>
>> unlock_page(page);
>> page_cache_release(page);
>> +#ifdef CONFIG_PNFS
>> + pnfs_free_fsdata(fsdata);
>> +#endif /* CONFIG_PNFS */
>>
>> return status < 0 ? status : copied;
>> }
>> diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
>> index 56aa1bf..a4db86e 100644
>> --- a/fs/nfs/pnfs.c
>> +++ b/fs/nfs/pnfs.c
>> @@ -809,6 +809,28 @@ pnfs_has_layout(struct pnfs_layout_type *lo,
>> return ret;
>> }
>>
>> +static struct pnfs_layout_segment *
>> +pnfs_find_get_lseg(struct inode *inode,
>> + loff_t pos,
>> + size_t count,
>> + enum pnfs_iomode iomode)
>> +{
>> + struct nfs_inode *nfsi = NFS_I(inode);
>> + struct pnfs_layout_segment *lseg;
>> + struct pnfs_layout_type *lo;
>> + struct nfs4_pnfs_layout_segment range;
>> +
>> + lo = get_lock_current_layout(nfsi);
>> + if (!lo)
>> + return NULL;
>> + range.iomode = iomode;
>> + range.offset = pos;
>> + range.length = count;
>> + lseg = pnfs_has_layout(lo, &range, 1);
>> + put_unlock_current_layout(nfsi, lo);
>> + return lseg;
>> +}
>> +
>> /* Update the file's layout for the given range and iomode.
>> * Layout is retreived from the server if needed.
>> * If lsegpp is given, the appropriate layout segment is referenced and
>> @@ -1537,6 +1559,64 @@ int pnfs_try_to_read_data(struct nfs_read_data *data,
>> }
>> }
>>
>> +/*
>> + * This gives the layout driver an opportunity to read in page "around"
>> + * the data to be written. It returns 0 on success, otherwise an error code
>> + * which will either be passed up to user, or ignored if
>> + * some previous part of write succeeded.
>> + * Note the range [pos, pos+len-1] is entirely within the page.
>> + */
>> +/* flags = AOP_FLAG_UNINTERRUPTIBLE or 0 - ??? need this ??? */
>> +int pnfs_write_begin(struct file *filp, struct page *page,
>> + loff_t pos, unsigned len,
>> + unsigned flags, void **fsdata)
>> +{
>> + struct inode *inode = filp->f_dentry->d_inode;
>> + struct nfs_server *nfss = NFS_SERVER(inode);
>> + struct pnfs_layout_segment *lseg;
>> + struct pnfs_fsdata *pnfs_fsdata = NULL;
>> + int status = 0;
>> +
>> + if (!nfss->pnfs_curr_ld || !nfss->pnfs_curr_ld->ld_io_ops ||
>> + !nfss->pnfs_curr_ld->ld_io_ops->write_begin) {
>> + /* If layout driver doesn't define, just do nothing */
>> + goto out;
>> + }
>> + lseg = pnfs_find_get_lseg(inode, pos, len, IOMODE_RW);
>> + status = nfss->pnfs_curr_ld->ld_io_ops->write_begin(lseg, page,
>> + pos, len,
>> + &pnfs_fsdata);
>> + put_lseg(lseg);
>> + if (pnfs_fsdata && !pnfs_fsdata->ld_io_ops)
>> + pnfs_fsdata->ld_io_ops = nfss->pnfs_curr_ld->ld_io_ops;
>> + out:
>> + *fsdata = pnfs_fsdata;
>
> One more comment. Can fsdata be NULL?
>
> Benny
>
>
Good question. Not in the path through generic_perform_write. I'll look
for other paths, and fix the function if needed.
Fred
More information about the pNFS
mailing list