diff options
| -rw-r--r-- | fs/nfs/delegation.c | 42 |
1 files changed, 28 insertions, 14 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 15671245c6ee..8d9ec494a944 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
| @@ -129,21 +129,35 @@ again: | |||
| 129 | */ | 129 | */ |
| 130 | void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res) | 130 | void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res) |
| 131 | { | 131 | { |
| 132 | struct nfs_delegation *delegation = NFS_I(inode)->delegation; | 132 | struct nfs_delegation *delegation; |
| 133 | struct rpc_cred *oldcred; | 133 | struct rpc_cred *oldcred = NULL; |
| 134 | 134 | ||
| 135 | if (delegation == NULL) | 135 | rcu_read_lock(); |
| 136 | return; | 136 | delegation = rcu_dereference(NFS_I(inode)->delegation); |
| 137 | memcpy(delegation->stateid.data, res->delegation.data, | 137 | if (delegation != NULL) { |
| 138 | sizeof(delegation->stateid.data)); | 138 | spin_lock(&delegation->lock); |
| 139 | delegation->type = res->delegation_type; | 139 | if (delegation->inode != NULL) { |
| 140 | delegation->maxsize = res->maxsize; | 140 | memcpy(delegation->stateid.data, res->delegation.data, |
| 141 | oldcred = delegation->cred; | 141 | sizeof(delegation->stateid.data)); |
| 142 | delegation->cred = get_rpccred(cred); | 142 | delegation->type = res->delegation_type; |
| 143 | clear_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags); | 143 | delegation->maxsize = res->maxsize; |
| 144 | NFS_I(inode)->delegation_state = delegation->type; | 144 | oldcred = delegation->cred; |
| 145 | smp_wmb(); | 145 | delegation->cred = get_rpccred(cred); |
| 146 | put_rpccred(oldcred); | 146 | clear_bit(NFS_DELEGATION_NEED_RECLAIM, |
| 147 | &delegation->flags); | ||
| 148 | NFS_I(inode)->delegation_state = delegation->type; | ||
| 149 | spin_unlock(&delegation->lock); | ||
| 150 | put_rpccred(oldcred); | ||
| 151 | rcu_read_unlock(); | ||
| 152 | } else { | ||
| 153 | /* We appear to have raced with a delegation return. */ | ||
| 154 | spin_unlock(&delegation->lock); | ||
| 155 | rcu_read_unlock(); | ||
| 156 | nfs_inode_set_delegation(inode, cred, res); | ||
| 157 | } | ||
| 158 | } else { | ||
| 159 | rcu_read_unlock(); | ||
| 160 | } | ||
| 147 | } | 161 | } |
| 148 | 162 | ||
| 149 | static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync) | 163 | static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync) |
