Loading fs/nfs/delegation.c +51 −38 Original line number Diff line number Diff line Loading @@ -125,6 +125,32 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, st put_rpccred(oldcred); } static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync) { int res = 0; res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid, issync); nfs_free_delegation(delegation); return res; } static struct nfs_delegation *nfs_detach_delegation_locked(struct nfs_inode *nfsi, const nfs4_stateid *stateid) { struct nfs_delegation *delegation = rcu_dereference(nfsi->delegation); if (delegation == NULL) goto nomatch; if (stateid != NULL && memcmp(delegation->stateid.data, stateid->data, sizeof(delegation->stateid.data)) != 0) goto nomatch; list_del_rcu(&delegation->super_list); nfsi->delegation_state = 0; rcu_assign_pointer(nfsi->delegation, NULL); return delegation; nomatch: return NULL; } /* * Set up a delegation on an inode */ Loading @@ -133,6 +159,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; struct nfs_inode *nfsi = NFS_I(inode); struct nfs_delegation *delegation; struct nfs_delegation *freeme = NULL; int status = 0; delegation = kmalloc(sizeof(*delegation), GFP_KERNEL); Loading @@ -147,42 +174,45 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct delegation->inode = inode; spin_lock(&clp->cl_lock); if (rcu_dereference(nfsi->delegation) == NULL) { list_add_rcu(&delegation->super_list, &clp->cl_delegations); nfsi->delegation_state = delegation->type; rcu_assign_pointer(nfsi->delegation, delegation); delegation = NULL; } else { if (rcu_dereference(nfsi->delegation) != NULL) { if (memcmp(&delegation->stateid, &nfsi->delegation->stateid, sizeof(delegation->stateid)) != 0 || delegation->type != nfsi->delegation->type) { printk(KERN_WARNING "%s: server %s handed out " sizeof(delegation->stateid)) == 0 && delegation->type == nfsi->delegation->type) { goto out; } /* * Deal with broken servers that hand out two * delegations for the same file. */ dfprintk(FILE, "%s: server %s handed out " "a duplicate delegation!\n", __FUNCTION__, clp->cl_hostname); status = -EIO; if (delegation->type <= nfsi->delegation->type) { freeme = delegation; delegation = NULL; goto out; } freeme = nfs_detach_delegation_locked(nfsi, NULL); } list_add_rcu(&delegation->super_list, &clp->cl_delegations); nfsi->delegation_state = delegation->type; rcu_assign_pointer(nfsi->delegation, delegation); delegation = NULL; /* Ensure we revalidate the attributes and page cache! */ spin_lock(&inode->i_lock); nfsi->cache_validity |= NFS_INO_REVAL_FORCED; spin_unlock(&inode->i_lock); out: spin_unlock(&clp->cl_lock); if (delegation != NULL) nfs_free_delegation(delegation); if (freeme != NULL) nfs_do_return_delegation(inode, freeme, 0); return status; } static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync) { int res = 0; res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid, issync); nfs_free_delegation(delegation); return res; } /* Sync all data to disk upon delegation return */ static void nfs_msync_inode(struct inode *inode) { Loading Loading @@ -211,23 +241,6 @@ static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegat return nfs_do_return_delegation(inode, delegation, 1); } static struct nfs_delegation *nfs_detach_delegation_locked(struct nfs_inode *nfsi, const nfs4_stateid *stateid) { struct nfs_delegation *delegation = rcu_dereference(nfsi->delegation); if (delegation == NULL) goto nomatch; if (stateid != NULL && memcmp(delegation->stateid.data, stateid->data, sizeof(delegation->stateid.data)) != 0) goto nomatch; list_del_rcu(&delegation->super_list); nfsi->delegation_state = 0; rcu_assign_pointer(nfsi->delegation, NULL); return delegation; nomatch: return NULL; } /* * This function returns the delegation without reclaiming opens * or protecting against delegation reclaims. Loading Loading
fs/nfs/delegation.c +51 −38 Original line number Diff line number Diff line Loading @@ -125,6 +125,32 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, st put_rpccred(oldcred); } static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync) { int res = 0; res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid, issync); nfs_free_delegation(delegation); return res; } static struct nfs_delegation *nfs_detach_delegation_locked(struct nfs_inode *nfsi, const nfs4_stateid *stateid) { struct nfs_delegation *delegation = rcu_dereference(nfsi->delegation); if (delegation == NULL) goto nomatch; if (stateid != NULL && memcmp(delegation->stateid.data, stateid->data, sizeof(delegation->stateid.data)) != 0) goto nomatch; list_del_rcu(&delegation->super_list); nfsi->delegation_state = 0; rcu_assign_pointer(nfsi->delegation, NULL); return delegation; nomatch: return NULL; } /* * Set up a delegation on an inode */ Loading @@ -133,6 +159,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; struct nfs_inode *nfsi = NFS_I(inode); struct nfs_delegation *delegation; struct nfs_delegation *freeme = NULL; int status = 0; delegation = kmalloc(sizeof(*delegation), GFP_KERNEL); Loading @@ -147,42 +174,45 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct delegation->inode = inode; spin_lock(&clp->cl_lock); if (rcu_dereference(nfsi->delegation) == NULL) { list_add_rcu(&delegation->super_list, &clp->cl_delegations); nfsi->delegation_state = delegation->type; rcu_assign_pointer(nfsi->delegation, delegation); delegation = NULL; } else { if (rcu_dereference(nfsi->delegation) != NULL) { if (memcmp(&delegation->stateid, &nfsi->delegation->stateid, sizeof(delegation->stateid)) != 0 || delegation->type != nfsi->delegation->type) { printk(KERN_WARNING "%s: server %s handed out " sizeof(delegation->stateid)) == 0 && delegation->type == nfsi->delegation->type) { goto out; } /* * Deal with broken servers that hand out two * delegations for the same file. */ dfprintk(FILE, "%s: server %s handed out " "a duplicate delegation!\n", __FUNCTION__, clp->cl_hostname); status = -EIO; if (delegation->type <= nfsi->delegation->type) { freeme = delegation; delegation = NULL; goto out; } freeme = nfs_detach_delegation_locked(nfsi, NULL); } list_add_rcu(&delegation->super_list, &clp->cl_delegations); nfsi->delegation_state = delegation->type; rcu_assign_pointer(nfsi->delegation, delegation); delegation = NULL; /* Ensure we revalidate the attributes and page cache! */ spin_lock(&inode->i_lock); nfsi->cache_validity |= NFS_INO_REVAL_FORCED; spin_unlock(&inode->i_lock); out: spin_unlock(&clp->cl_lock); if (delegation != NULL) nfs_free_delegation(delegation); if (freeme != NULL) nfs_do_return_delegation(inode, freeme, 0); return status; } static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync) { int res = 0; res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid, issync); nfs_free_delegation(delegation); return res; } /* Sync all data to disk upon delegation return */ static void nfs_msync_inode(struct inode *inode) { Loading Loading @@ -211,23 +241,6 @@ static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegat return nfs_do_return_delegation(inode, delegation, 1); } static struct nfs_delegation *nfs_detach_delegation_locked(struct nfs_inode *nfsi, const nfs4_stateid *stateid) { struct nfs_delegation *delegation = rcu_dereference(nfsi->delegation); if (delegation == NULL) goto nomatch; if (stateid != NULL && memcmp(delegation->stateid.data, stateid->data, sizeof(delegation->stateid.data)) != 0) goto nomatch; list_del_rcu(&delegation->super_list); nfsi->delegation_state = 0; rcu_assign_pointer(nfsi->delegation, NULL); return delegation; nomatch: return NULL; } /* * This function returns the delegation without reclaiming opens * or protecting against delegation reclaims. Loading