

Override standard NFS fsync processing to call the layout driver fsync
operation if it exists.


---

 linux-2.6.14-pnfs-current-dhildebz/fs/nfs/file.c |    7 +-
 linux-2.6.14-pnfs-current-dhildebz/fs/nfs/pnfs.c |   56 +++++++++++++++++++++++
 linux-2.6.14-pnfs-current-dhildebz/fs/nfs/pnfs.h |    2 
 3 files changed, 61 insertions(+), 4 deletions(-)

diff -puN fs/nfs/file.c~client-fsync fs/nfs/file.c
--- linux-2.6.14-pnfs-current/fs/nfs/file.c~client-fsync	2006-01-12 17:03:27.590226000 -0500
+++ linux-2.6.14-pnfs-current-dhildebz/fs/nfs/file.c	2006-01-12 17:03:27.616226000 -0500
@@ -44,7 +44,7 @@ static ssize_t nfs_file_sendfile(struct 
 static ssize_t nfs_file_read(struct kiocb *, char __user *, size_t, loff_t);
 static ssize_t nfs_file_write(struct kiocb *, const char __user *, size_t, loff_t);
 static int  nfs_file_flush(struct file *);
-static int  nfs_fsync(struct file *, struct dentry *dentry, int datasync);
+int  nfs_fsync(struct file *, struct dentry *dentry, int datasync);
 static int nfs_check_flags(int flags);
 static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl);
 static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl);
@@ -54,9 +54,11 @@ struct file_operations nfs_file_operatio
 #ifdef CONFIG_NFS_V4
 	.read           = pnfs_file_read,
 	.write          = pnfs_file_write,
+	.fsync		= pnfs_fsync,
 #else
 	.read           = do_sync_read,
 	.write          = do_sync_write,
+	.fsync		= nfs_fsync,
 #endif
 	.aio_read		= nfs_file_read,
 	.aio_write		= nfs_file_write,
@@ -64,7 +66,6 @@ struct file_operations nfs_file_operatio
 	.open		= nfs_file_open,
 	.flush		= nfs_file_flush,
 	.release	= nfs_file_release,
-	.fsync		= nfs_fsync,
 	.lock		= nfs_lock,
 	.flock		= nfs_flock,
 	.sendfile	= nfs_file_sendfile,
@@ -279,7 +280,7 @@ nfs_file_mmap(struct file * file, struct
  * The return status from this call provides a reliable indication of
  * whether any write errors occurred for this process.
  */
-static int
+int
 nfs_fsync(struct file *file, struct dentry *dentry, int datasync)
 {
 	struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data;
diff -puN fs/nfs/pnfs.c~client-fsync fs/nfs/pnfs.c
--- linux-2.6.14-pnfs-current/fs/nfs/pnfs.c~client-fsync	2006-01-12 17:03:27.603226000 -0500
+++ linux-2.6.14-pnfs-current-dhildebz/fs/nfs/pnfs.c	2006-01-12 17:03:27.623226000 -0500
@@ -56,6 +56,7 @@ extern void nfs_writepage_release(struct
 extern void nfs_inode_remove_request(struct nfs_page *req);
 extern void nfs_mark_request_commit(struct nfs_page *req);
 extern void nfs_writeback_done_full(struct nfs_write_data *data, int status);
+extern int nfs_fsync(struct file *file, struct dentry *dentry, int datasync);
 
 /* Locking:
  *
@@ -765,5 +766,60 @@ pnfs_commit(struct inode* inode, struct 
 	return result;
 }
 
+int
+pnfs_fsync(struct file *file, struct dentry *dentry, int datasync)
+{
+	int result = 0;
+	struct inode *inode = dentry->d_inode;
+	struct nfs_inode *nfsi = NFS_I(inode);
+	int req_nfs_flush = nfsi->ndirty;
+	int req_nfs_commit = nfsi->ncommit;
+	int nfs_dirty = nfsi->nfs_dirty;
+	int pnfs_dirty = nfsi->pnfs_dirty;
+	struct nfs_server* nfss = NFS_SERVER(inode);
+	dprintk("%s: Begin\n",__FUNCTION__);
+
+	/* pNFS is only for v4
+	 * Only fsync nfs if an outstanding nfs request requires it
+	 * Some problems seem to be happening if ncommit and ndirty are both 0 and I still
+	 * don't call nfs_fsync
+	 */
+	if (nfss->rpc_ops->version != 4 ||
+	    !nfss->pnfs_curr_ld ||
+	    nfs_dirty)
+	{
+		dfprintk(IO, "%s: Calling nfs_fsync f:%d c:%d d:%d\n",__FUNCTION__,req_nfs_flush, req_nfs_commit, nfs_dirty);
+		result = nfs_fsync(file,dentry,datasync);
+		/* reset dirty flag from writing below threshold */
+		nfsi->nfs_dirty = 0;
+	}
+	else if (nfss->pnfs_curr_ld->ld_io_ops->fsync && pnfs_dirty)
+	{
+		/* Retrieve and set layout if not allready cached.
+		 * This is necessary since read/write may not have necessarily
+		 * been already called.  Just put in any random count and offset.
+		 * May need special count and offset depending on how file system
+		 * work that actually pay attention to such values.
+		 */
+		if ((result = virtual_update_layout(inode,
+						    (struct nfs_open_context *)file->private_data,
+						    0,
+						    0,
+						    FMODE_WRITE)))
+		{
+			return result;
+		}
+		dfprintk(IO, "%s: Calling layout driver fsync\n",__FUNCTION__);
+		result = nfss->pnfs_curr_ld->ld_io_ops->fsync(nfsi->current_layout, file, dentry, datasync);
+		/* Reset dirty flag to avoid unecessary syncs
+		 * TODO: Only reset if fsync succeeds.
+		 */
+		nfsi->pnfs_dirty = 0;
+	}
+
+	dprintk("%s end (err:%Zd)\n",__FUNCTION__,result);
+	return result;
+}
+
 EXPORT_SYMBOL(pnfs_unregister_layoutdriver);
 EXPORT_SYMBOL(pnfs_register_layoutdriver);
diff -puN fs/nfs/pnfs.h~client-fsync fs/nfs/pnfs.h
--- linux-2.6.14-pnfs-current/fs/nfs/pnfs.h~client-fsync	2006-01-12 17:03:27.607227000 -0500
+++ linux-2.6.14-pnfs-current-dhildebz/fs/nfs/pnfs.h	2006-01-12 17:03:27.627227000 -0500
@@ -20,5 +20,5 @@ int use_pnfs_io(struct inode *inode,unsi
 int pnfs_writepages(struct nfs_write_data *wdata);
 void pnfs_writeback_done(struct nfs_write_data *data, int status);
 int pnfs_readpages(struct nfs_read_data *rdata);
-
+int pnfs_fsync(struct file *file, struct dentry *dentry, int datasync);
 #endif /* FS_NFS_PNFS_H */
_
