[pnfs] [PATCH 8/8] pnfs: pnfs_write_end

Fred Isaman iisaman at citi.umich.edu
Thu May 1 09:02:17 EDT 2008


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             |   17 +++++++++++++++++
 fs/nfs/pnfs.h             |   23 +++++++++++++++++++++++
 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 98e9d8f..ace9d73 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -375,10 +375,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 c964beb..41950df 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1596,6 +1596,23 @@ int _pnfs_write_begin(struct inode *inode, struct page *page,
 	return status;
 }
 
+/* Return 0 on succes, negative on failure */
+/* CAREFUL - what happens if copied < len??? */
+int _pnfs_write_end(struct inode *inode, struct page *page,
+		    loff_t pos, unsigned len,
+		    unsigned copied, struct pnfs_fsdata *fsdata)
+{
+	struct nfs_server *nfss = NFS_SERVER(inode);
+	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 d6fca00..acbce4b 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -62,6 +62,9 @@ void pnfs_get_layout_done(struct pnfs_layout_type *,
 void pnfs_layout_release(struct pnfs_layout_type *);
 int _pnfs_write_begin(struct inode *inode, struct page *page,
 		      loff_t pos, unsigned len, void **fsdata);
+int _pnfs_write_end(struct inode *inode, struct page *page,
+		    loff_t pos, unsigned len,
+		    unsigned copied, struct pnfs_fsdata *fsdata);
 int _pnfs_do_flush(struct inode *inode, struct nfs_page *req,
 		   struct pnfs_fsdata *fsdata);
 void _pnfs_modify_new_write_request(struct nfs_page *req,
@@ -147,6 +150,19 @@ 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, page, pos, len, copied, fsdata);
+	else
+		return 0;
+}
+
 static inline void pnfs_write_end_cleanup(void *fsdata)
 {
 	pnfs_free_fsdata(fsdata);
@@ -196,6 +212,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 736bde7..0da5280 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) || pnfs_do_flush(req, NULL)
+	    || !nfs_dirty_request(req) || pnfs_do_flush(req, fsdata)
 	    || 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 e893ca6..c83aae6 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);
-- 
1.5.3.3



More information about the pNFS mailing list