[pnfs] [PATCH 07/11] pnfs: pnfs_write_end
Benny Halevy
bhalevy at panasas.com
Sun Apr 13 10:07:02 EDT 2008
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.
> + 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?
> || 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