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 */ _