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