diff options
Diffstat (limited to 'fs/nfs/delegation.c')
| -rw-r--r-- | fs/nfs/delegation.c | 47 | 
1 files changed, 45 insertions, 2 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 618a327027b3..c6f07c1c71e6 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c  | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | */ | 8 | */ | 
| 9 | #include <linux/config.h> | 9 | #include <linux/config.h> | 
| 10 | #include <linux/completion.h> | 10 | #include <linux/completion.h> | 
| 11 | #include <linux/kthread.h> | ||
| 11 | #include <linux/module.h> | 12 | #include <linux/module.h> | 
| 12 | #include <linux/sched.h> | 13 | #include <linux/sched.h> | 
| 13 | #include <linux/spinlock.h> | 14 | #include <linux/spinlock.h> | 
| @@ -130,6 +131,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct | |||
| 130 | sizeof(delegation->stateid.data)); | 131 | sizeof(delegation->stateid.data)); | 
| 131 | delegation->type = res->delegation_type; | 132 | delegation->type = res->delegation_type; | 
| 132 | delegation->maxsize = res->maxsize; | 133 | delegation->maxsize = res->maxsize; | 
| 134 | delegation->change_attr = nfsi->change_attr; | ||
| 133 | delegation->cred = get_rpccred(cred); | 135 | delegation->cred = get_rpccred(cred); | 
| 134 | delegation->inode = inode; | 136 | delegation->inode = inode; | 
| 135 | 137 | ||
| @@ -157,8 +159,6 @@ static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation * | |||
| 157 | { | 159 | { | 
| 158 | int res = 0; | 160 | int res = 0; | 
| 159 | 161 | ||
| 160 | __nfs_revalidate_inode(NFS_SERVER(inode), inode); | ||
| 161 | |||
| 162 | res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid); | 162 | res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid); | 
| 163 | nfs_free_delegation(delegation); | 163 | nfs_free_delegation(delegation); | 
| 164 | return res; | 164 | return res; | 
| @@ -231,6 +231,49 @@ restart: | |||
| 231 | spin_unlock(&clp->cl_lock); | 231 | spin_unlock(&clp->cl_lock); | 
| 232 | } | 232 | } | 
| 233 | 233 | ||
| 234 | int nfs_do_expire_all_delegations(void *ptr) | ||
| 235 | { | ||
| 236 | struct nfs4_client *clp = ptr; | ||
| 237 | struct nfs_delegation *delegation; | ||
| 238 | struct inode *inode; | ||
| 239 | |||
| 240 | allow_signal(SIGKILL); | ||
| 241 | restart: | ||
| 242 | spin_lock(&clp->cl_lock); | ||
| 243 | if (test_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) != 0) | ||
| 244 | goto out; | ||
| 245 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) | ||
| 246 | goto out; | ||
| 247 | list_for_each_entry(delegation, &clp->cl_delegations, super_list) { | ||
| 248 | inode = igrab(delegation->inode); | ||
| 249 | if (inode == NULL) | ||
| 250 | continue; | ||
| 251 | spin_unlock(&clp->cl_lock); | ||
| 252 | nfs_inode_return_delegation(inode); | ||
| 253 | iput(inode); | ||
| 254 | goto restart; | ||
| 255 | } | ||
| 256 | out: | ||
| 257 | spin_unlock(&clp->cl_lock); | ||
| 258 | nfs4_put_client(clp); | ||
| 259 | module_put_and_exit(0); | ||
| 260 | } | ||
| 261 | |||
| 262 | void nfs_expire_all_delegations(struct nfs4_client *clp) | ||
| 263 | { | ||
| 264 | struct task_struct *task; | ||
| 265 | |||
| 266 | __module_get(THIS_MODULE); | ||
| 267 | atomic_inc(&clp->cl_count); | ||
| 268 | task = kthread_run(nfs_do_expire_all_delegations, clp, | ||
| 269 | "%u.%u.%u.%u-delegreturn", | ||
| 270 | NIPQUAD(clp->cl_addr)); | ||
| 271 | if (!IS_ERR(task)) | ||
| 272 | return; | ||
| 273 | nfs4_put_client(clp); | ||
| 274 | module_put(THIS_MODULE); | ||
| 275 | } | ||
| 276 | |||
| 234 | /* | 277 | /* | 
| 235 | * Return all delegations following an NFS4ERR_CB_PATH_DOWN error. | 278 | * Return all delegations following an NFS4ERR_CB_PATH_DOWN error. | 
| 236 | */ | 279 | */ | 
