fs/nfs/delegation.c | 6 ++++++ fs/nfs/delegation.h | 16 ++++++++++++++++ fs/nfs/dir.c | 4 ++++ fs/nfs/file.c | 4 +++- fs/nfs/inode.c | 48 ++++++++++++++++++++++++++++++++++++++++-------- fs/nfs/write.c | 7 +++++-- include/linux/nfs_fs.h | 25 +++---------------------- 7 files changed, 77 insertions(+), 33 deletions(-) diff -u --recursive --new-file --show-c-function linux-2.6.7-18-delegation_open/fs/nfs/delegation.c linux-2.6.7-19-delegation_cache/fs/nfs/delegation.c --- linux-2.6.7-18-delegation_open/fs/nfs/delegation.c 2004-06-15 01:14:30.000000000 -0400 +++ linux-2.6.7-19-delegation_cache/fs/nfs/delegation.c 2004-06-15 01:14:46.000000000 -0400 @@ -70,6 +70,8 @@ void nfs_inode_reclaim_delegation(struct put_rpccred(cred); delegation->cred = get_rpccred(cred); delegation->flags &= ~NFS_DELEGATION_NEED_RECLAIM; + NFS_I(inode)->delegation_state = delegation->type; + smp_wmb(); } /* @@ -96,6 +98,7 @@ int nfs_inode_set_delegation(struct inod if (nfsi->delegation == NULL) { list_add(&delegation->super_list, &clp->cl_delegations); nfsi->delegation = delegation; + nfsi->delegation_state = delegation->type; delegation = NULL; } else { if (memcmp(&delegation->stateid, &nfsi->delegation->stateid, @@ -142,6 +145,7 @@ int nfs_inode_return_delegation(struct i if (delegation != NULL) { list_del_init(&delegation->super_list); nfsi->delegation = NULL; + nfsi->delegation_state = 0; } spin_unlock(&clp->cl_lock); nfs_delegation_claim_opens(inode); @@ -210,6 +214,7 @@ static int recall_thread(void *data) sizeof(delegation->stateid.data)) == 0) { list_del_init(&delegation->super_list); nfsi->delegation = NULL; + nfsi->delegation_state = 0; args->result = 0; } else { delegation = NULL; @@ -295,6 +300,7 @@ void nfs_delegation_reap_unclaimed(struc continue; list_move(&delegation->super_list, &head); NFS_I(delegation->inode)->delegation = NULL; + NFS_I(delegation->inode)->delegation_state = 0; } spin_unlock(&clp->cl_lock); while(!list_empty(&head)) { diff -u --recursive --new-file --show-c-function linux-2.6.7-18-delegation_open/fs/nfs/delegation.h linux-2.6.7-19-delegation_cache/fs/nfs/delegation.h --- linux-2.6.7-18-delegation_open/fs/nfs/delegation.h 2004-06-15 01:40:51.000000000 -0400 +++ linux-2.6.7-19-delegation_cache/fs/nfs/delegation.h 2004-06-15 01:41:02.000000000 -0400 @@ -8,6 +8,7 @@ #ifndef FS_NFS_DELEGATION_H #define FS_NFS_DELEGATION_H +#if defined(CONFIG_NFS_V4) /* * NFSv4 delegation */ @@ -37,4 +38,19 @@ void nfs_delegation_reap_unclaimed(struc int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid); int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state); +static inline int nfs_have_delegation(struct inode *inode, int flags) +{ + flags &= FMODE_READ|FMODE_WRITE; + smp_rmb(); + if ((NFS_I(inode)->delegation_state & flags) == flags) + return 1; + return 0; +} +#else +static inline int nfs_have_delegation(struct inode *inode, int flags) +{ + return 0; +} +#endif + #endif diff -u --recursive --new-file --show-c-function linux-2.6.7-18-delegation_open/fs/nfs/dir.c linux-2.6.7-19-delegation_cache/fs/nfs/dir.c --- linux-2.6.7-18-delegation_open/fs/nfs/dir.c 2004-06-15 00:01:20.000000000 -0400 +++ linux-2.6.7-19-delegation_cache/fs/nfs/dir.c 2004-06-15 00:01:27.000000000 -0400 @@ -32,6 +32,8 @@ #include #include +#include "delegation.h" + #define NFS_PARANOIA 1 /* #define NFS_DEBUG_VERBOSE 1 */ @@ -887,6 +889,8 @@ out: return ret; no_open: dput(parent); + if (inode != NULL && nfs_have_delegation(inode, FMODE_READ)) + return 1; return nfs_lookup_revalidate(dentry, nd); } #endif /* CONFIG_NFSV4 */ diff -u --recursive --new-file --show-c-function linux-2.6.7-18-delegation_open/fs/nfs/file.c linux-2.6.7-19-delegation_cache/fs/nfs/file.c --- linux-2.6.7-18-delegation_open/fs/nfs/file.c 2004-06-15 00:00:23.000000000 -0400 +++ linux-2.6.7-19-delegation_cache/fs/nfs/file.c 2004-06-15 00:01:27.000000000 -0400 @@ -31,6 +31,8 @@ #include #include +#include "delegation.h" + #define NFSDBG_FACILITY NFSDBG_FILE static long nfs_file_fcntl(int fd, unsigned int cmd, @@ -141,7 +143,7 @@ nfs_file_flush(struct file *file) if (!status) { status = ctx->error; ctx->error = 0; - if (!status) + if (!status && !nfs_have_delegation(inode, FMODE_READ)) __nfs_revalidate_inode(NFS_SERVER(inode), inode); } unlock_kernel(); diff -u --recursive --new-file --show-c-function linux-2.6.7-18-delegation_open/fs/nfs/inode.c linux-2.6.7-19-delegation_cache/fs/nfs/inode.c --- linux-2.6.7-18-delegation_open/fs/nfs/inode.c 2004-06-15 00:00:35.000000000 -0400 +++ linux-2.6.7-19-delegation_cache/fs/nfs/inode.c 2004-06-15 01:58:19.000000000 -0400 @@ -39,6 +39,8 @@ #include #include +#include "delegation.h" + #define NFSDBG_FACILITY NFSDBG_VFS #define NFS_PARANOIA 1 @@ -1064,6 +1066,30 @@ out: return status; } +int nfs_attribute_timeout(struct inode *inode) +{ + struct nfs_inode *nfsi = NFS_I(inode); + + if (nfs_have_delegation(inode, FMODE_READ)) + return 0; + return time_after(jiffies, nfsi->read_cache_jiffies+nfsi->attrtimeo); +} + +/** + * nfs_revalidate_inode - Revalidate the inode attributes + * @server - pointer to nfs_server struct + * @inode - pointer to inode struct + * + * Updates inode attribute information by retrieving the data from the server. + */ +int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) +{ + if (!(NFS_FLAGS(inode) & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA)) + && !nfs_attribute_timeout(inode)) + return NFS_STALE(inode) ? -ESTALE : 0; + return __nfs_revalidate_inode(server, inode); +} + /** * nfs_begin_data_update * @inode - pointer to inode @@ -1085,11 +1111,13 @@ void nfs_end_data_update(struct inode *i { struct nfs_inode *nfsi = NFS_I(inode); - /* Mark the attribute cache for revalidation */ - nfsi->flags |= NFS_INO_INVALID_ATTR; - /* Directories and symlinks: invalidate page cache too */ - if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) - nfsi->flags |= NFS_INO_INVALID_DATA; + if (!nfs_have_delegation(inode, FMODE_READ)) { + /* Mark the attribute cache for revalidation */ + nfsi->flags |= NFS_INO_INVALID_ATTR; + /* Directories and symlinks: invalidate page cache too */ + if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) + nfsi->flags |= NFS_INO_INVALID_DATA; + } nfsi->cache_change_attribute ++; atomic_dec(&nfsi->data_updates); } @@ -1130,6 +1158,10 @@ int nfs_refresh_inode(struct inode *inod loff_t cur_size, new_isize; int data_unstable; + /* Do we hold a delegation? */ + if (nfs_have_delegation(inode, FMODE_READ)) + return 0; + /* Are we in the process of updating data on the server? */ data_unstable = nfs_caches_unstable(inode); @@ -1327,7 +1359,8 @@ static int nfs_update_inode(struct inode if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))) invalid &= ~NFS_INO_INVALID_DATA; - nfsi->flags |= invalid; + if (!nfs_have_delegation(inode, FMODE_READ)) + nfsi->flags |= invalid; return 0; out_changed: @@ -1462,8 +1495,6 @@ static struct file_system_type nfs_fs_ty #ifdef CONFIG_NFS_V4 -#include "delegation.h" - static void nfs4_clear_inode(struct inode *); @@ -1801,6 +1832,7 @@ static struct file_system_type nfs4_fs_t do { \ INIT_LIST_HEAD(&(nfsi)->open_states); \ nfsi->delegation = NULL; \ + nfsi->delegation_state = 0; \ init_rwsem(&nfsi->rwsem); \ } while(0) #define register_nfs4fs() register_filesystem(&nfs4_fs_type) diff -u --recursive --new-file --show-c-function linux-2.6.7-18-delegation_open/fs/nfs/write.c linux-2.6.7-19-delegation_cache/fs/nfs/write.c --- linux-2.6.7-18-delegation_open/fs/nfs/write.c 2004-06-15 00:00:29.000000000 -0400 +++ linux-2.6.7-19-delegation_cache/fs/nfs/write.c 2004-06-15 00:01:27.000000000 -0400 @@ -63,6 +63,8 @@ #include #include +#include "delegation.h" + #define NFSDBG_FACILITY NFSDBG_PAGECACHE #define MIN_POOL_WRITE (32) @@ -384,8 +386,7 @@ out: /* * Insert a write request into an inode */ -static inline int -nfs_inode_add_request(struct inode *inode, struct nfs_page *req) +static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req) { struct nfs_inode *nfsi = NFS_I(inode); int error; @@ -397,6 +398,8 @@ nfs_inode_add_request(struct inode *inod if (!nfsi->npages) { igrab(inode); nfs_begin_data_update(inode); + if (nfs_have_delegation(inode, FMODE_WRITE)) + nfsi->change_attr++; } nfsi->npages++; req->wb_count++; diff -u --recursive --new-file --show-c-function linux-2.6.7-18-delegation_open/include/linux/nfs_fs.h linux-2.6.7-19-delegation_cache/include/linux/nfs_fs.h --- linux-2.6.7-18-delegation_open/include/linux/nfs_fs.h 2004-06-15 00:01:20.000000000 -0400 +++ linux-2.6.7-19-delegation_cache/include/linux/nfs_fs.h 2004-06-15 00:01:28.000000000 -0400 @@ -184,6 +184,7 @@ struct nfs_inode { /* NFSv4 state */ struct list_head open_states; struct nfs_delegation *delegation; + int delegation_state; struct rw_semaphore rwsem; #endif /* CONFIG_NFS_V4*/ @@ -305,6 +306,8 @@ extern int nfs_access_get_cached(struct extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *); extern int nfs_open(struct inode *, struct file *); extern int nfs_release(struct inode *, struct file *); +extern int nfs_attribute_timeout(struct inode *inode); +extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode); extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *); extern int nfs_setattr(struct dentry *, struct iattr *); extern void nfs_begin_attr_update(struct inode *); @@ -457,28 +460,6 @@ extern int nfsroot_mount(struct sockadd * inline functions */ -static inline int nfs_attribute_timeout(struct inode *inode) -{ - struct nfs_inode *nfsi = NFS_I(inode); - - return time_after(jiffies, nfsi->read_cache_jiffies+nfsi->attrtimeo); -} - -/** - * nfs_revalidate_inode - Revalidate the inode attributes - * @server - pointer to nfs_server struct - * @inode - pointer to inode struct - * - * Updates inode attribute information by retrieving the data from the server. - */ -static inline int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) -{ - if (!(NFS_FLAGS(inode) & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA)) - && !nfs_attribute_timeout(inode)) - return NFS_STALE(inode) ? -ESTALE : 0; - return __nfs_revalidate_inode(server, inode); -} - static inline loff_t nfs_size_to_loff_t(__u64 size) {