Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[wrt350n-kernel.git] / fs / nfs / delegation.c
blob2452931392e7ccb05c24eb46ae2a0a0305c09628
1 /*
2 * linux/fs/nfs/delegation.c
4 * Copyright (C) 2004 Trond Myklebust
6 * NFS file delegation management
8 */
9 #include <linux/completion.h>
10 #include <linux/kthread.h>
11 #include <linux/module.h>
12 #include <linux/sched.h>
13 #include <linux/spinlock.h>
15 #include <linux/nfs4.h>
16 #include <linux/nfs_fs.h>
17 #include <linux/nfs_xdr.h>
19 #include "nfs4_fs.h"
20 #include "delegation.h"
21 #include "internal.h"
23 static void nfs_do_free_delegation(struct nfs_delegation *delegation)
25 kfree(delegation);
28 static void nfs_free_delegation_callback(struct rcu_head *head)
30 struct nfs_delegation *delegation = container_of(head, struct nfs_delegation, rcu);
32 nfs_do_free_delegation(delegation);
35 static void nfs_free_delegation(struct nfs_delegation *delegation)
37 struct rpc_cred *cred;
39 cred = rcu_dereference(delegation->cred);
40 rcu_assign_pointer(delegation->cred, NULL);
41 call_rcu(&delegation->rcu, nfs_free_delegation_callback);
42 if (cred)
43 put_rpccred(cred);
46 static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_state *state)
48 struct inode *inode = state->inode;
49 struct file_lock *fl;
50 int status;
52 <<<<<<< HEAD:fs/nfs/delegation.c
53 for (fl = inode->i_flock; fl != 0; fl = fl->fl_next) {
54 =======
55 for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
56 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a:fs/nfs/delegation.c
57 if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
58 continue;
59 if (nfs_file_open_context(fl->fl_file) != ctx)
60 continue;
61 status = nfs4_lock_delegation_recall(state, fl);
62 if (status >= 0)
63 continue;
64 switch (status) {
65 default:
66 printk(KERN_ERR "%s: unhandled error %d.\n",
67 __FUNCTION__, status);
68 case -NFS4ERR_EXPIRED:
69 /* kill_proc(fl->fl_pid, SIGLOST, 1); */
70 case -NFS4ERR_STALE_CLIENTID:
71 nfs4_schedule_state_recovery(NFS_SERVER(inode)->nfs_client);
72 goto out_err;
75 return 0;
76 out_err:
77 return status;
80 static void nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *stateid)
82 struct nfs_inode *nfsi = NFS_I(inode);
83 struct nfs_open_context *ctx;
84 struct nfs4_state *state;
85 int err;
87 again:
88 spin_lock(&inode->i_lock);
89 list_for_each_entry(ctx, &nfsi->open_files, list) {
90 state = ctx->state;
91 if (state == NULL)
92 continue;
93 if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
94 continue;
95 if (memcmp(state->stateid.data, stateid->data, sizeof(state->stateid.data)) != 0)
96 continue;
97 get_nfs_open_context(ctx);
98 spin_unlock(&inode->i_lock);
99 err = nfs4_open_delegation_recall(ctx, state, stateid);
100 if (err >= 0)
101 err = nfs_delegation_claim_locks(ctx, state);
102 put_nfs_open_context(ctx);
103 if (err != 0)
104 return;
105 goto again;
107 spin_unlock(&inode->i_lock);
111 * Set up a delegation on an inode
113 void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res)
115 struct nfs_delegation *delegation = NFS_I(inode)->delegation;
116 struct rpc_cred *oldcred;
118 if (delegation == NULL)
119 return;
120 memcpy(delegation->stateid.data, res->delegation.data,
121 sizeof(delegation->stateid.data));
122 delegation->type = res->delegation_type;
123 delegation->maxsize = res->maxsize;
124 oldcred = delegation->cred;
125 delegation->cred = get_rpccred(cred);
126 delegation->flags &= ~NFS_DELEGATION_NEED_RECLAIM;
127 NFS_I(inode)->delegation_state = delegation->type;
128 smp_wmb();
129 put_rpccred(oldcred);
132 static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync)
134 int res = 0;
136 res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid, issync);
137 nfs_free_delegation(delegation);
138 return res;
141 static struct nfs_delegation *nfs_detach_delegation_locked(struct nfs_inode *nfsi, const nfs4_stateid *stateid)
143 struct nfs_delegation *delegation = rcu_dereference(nfsi->delegation);
145 if (delegation == NULL)
146 goto nomatch;
147 if (stateid != NULL && memcmp(delegation->stateid.data, stateid->data,
148 sizeof(delegation->stateid.data)) != 0)
149 goto nomatch;
150 list_del_rcu(&delegation->super_list);
151 nfsi->delegation_state = 0;
152 rcu_assign_pointer(nfsi->delegation, NULL);
153 return delegation;
154 nomatch:
155 return NULL;
159 * Set up a delegation on an inode
161 int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res)
163 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
164 struct nfs_inode *nfsi = NFS_I(inode);
165 struct nfs_delegation *delegation;
166 struct nfs_delegation *freeme = NULL;
167 int status = 0;
169 delegation = kmalloc(sizeof(*delegation), GFP_KERNEL);
170 if (delegation == NULL)
171 return -ENOMEM;
172 memcpy(delegation->stateid.data, res->delegation.data,
173 sizeof(delegation->stateid.data));
174 delegation->type = res->delegation_type;
175 delegation->maxsize = res->maxsize;
176 delegation->change_attr = nfsi->change_attr;
177 delegation->cred = get_rpccred(cred);
178 delegation->inode = inode;
180 spin_lock(&clp->cl_lock);
181 if (rcu_dereference(nfsi->delegation) != NULL) {
182 if (memcmp(&delegation->stateid, &nfsi->delegation->stateid,
183 sizeof(delegation->stateid)) == 0 &&
184 delegation->type == nfsi->delegation->type) {
185 goto out;
188 * Deal with broken servers that hand out two
189 * delegations for the same file.
191 dfprintk(FILE, "%s: server %s handed out "
192 "a duplicate delegation!\n",
193 __FUNCTION__, clp->cl_hostname);
194 if (delegation->type <= nfsi->delegation->type) {
195 freeme = delegation;
196 delegation = NULL;
197 goto out;
199 freeme = nfs_detach_delegation_locked(nfsi, NULL);
201 list_add_rcu(&delegation->super_list, &clp->cl_delegations);
202 nfsi->delegation_state = delegation->type;
203 rcu_assign_pointer(nfsi->delegation, delegation);
204 delegation = NULL;
206 /* Ensure we revalidate the attributes and page cache! */
207 spin_lock(&inode->i_lock);
208 nfsi->cache_validity |= NFS_INO_REVAL_FORCED;
209 spin_unlock(&inode->i_lock);
211 out:
212 spin_unlock(&clp->cl_lock);
213 if (delegation != NULL)
214 nfs_free_delegation(delegation);
215 if (freeme != NULL)
216 nfs_do_return_delegation(inode, freeme, 0);
217 return status;
220 /* Sync all data to disk upon delegation return */
221 static void nfs_msync_inode(struct inode *inode)
223 filemap_fdatawrite(inode->i_mapping);
224 nfs_wb_all(inode);
225 filemap_fdatawait(inode->i_mapping);
229 * Basic procedure for returning a delegation to the server
231 static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation)
233 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
234 struct nfs_inode *nfsi = NFS_I(inode);
236 nfs_msync_inode(inode);
237 down_read(&clp->cl_sem);
238 /* Guard against new delegated open calls */
239 down_write(&nfsi->rwsem);
240 nfs_delegation_claim_opens(inode, &delegation->stateid);
241 up_write(&nfsi->rwsem);
242 up_read(&clp->cl_sem);
243 nfs_msync_inode(inode);
245 return nfs_do_return_delegation(inode, delegation, 1);
249 * This function returns the delegation without reclaiming opens
250 * or protecting against delegation reclaims.
251 * It is therefore really only safe to be called from
252 * nfs4_clear_inode()
254 void nfs_inode_return_delegation_noreclaim(struct inode *inode)
256 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
257 struct nfs_inode *nfsi = NFS_I(inode);
258 struct nfs_delegation *delegation;
260 if (rcu_dereference(nfsi->delegation) != NULL) {
261 spin_lock(&clp->cl_lock);
262 delegation = nfs_detach_delegation_locked(nfsi, NULL);
263 spin_unlock(&clp->cl_lock);
264 if (delegation != NULL)
265 nfs_do_return_delegation(inode, delegation, 0);
269 int nfs_inode_return_delegation(struct inode *inode)
271 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
272 struct nfs_inode *nfsi = NFS_I(inode);
273 struct nfs_delegation *delegation;
274 int err = 0;
276 if (rcu_dereference(nfsi->delegation) != NULL) {
277 spin_lock(&clp->cl_lock);
278 delegation = nfs_detach_delegation_locked(nfsi, NULL);
279 spin_unlock(&clp->cl_lock);
280 if (delegation != NULL)
281 err = __nfs_inode_return_delegation(inode, delegation);
283 return err;
287 * Return all delegations associated to a super block
289 void nfs_return_all_delegations(struct super_block *sb)
291 struct nfs_client *clp = NFS_SB(sb)->nfs_client;
292 struct nfs_delegation *delegation;
293 struct inode *inode;
295 if (clp == NULL)
296 return;
297 restart:
298 rcu_read_lock();
299 list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
300 if (delegation->inode->i_sb != sb)
301 continue;
302 inode = igrab(delegation->inode);
303 if (inode == NULL)
304 continue;
305 spin_lock(&clp->cl_lock);
306 delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
307 spin_unlock(&clp->cl_lock);
308 rcu_read_unlock();
309 if (delegation != NULL)
310 __nfs_inode_return_delegation(inode, delegation);
311 iput(inode);
312 goto restart;
314 rcu_read_unlock();
317 static int nfs_do_expire_all_delegations(void *ptr)
319 struct nfs_client *clp = ptr;
320 struct nfs_delegation *delegation;
321 struct inode *inode;
323 allow_signal(SIGKILL);
324 restart:
325 if (test_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) != 0)
326 goto out;
327 if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0)
328 goto out;
329 rcu_read_lock();
330 list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
331 inode = igrab(delegation->inode);
332 if (inode == NULL)
333 continue;
334 spin_lock(&clp->cl_lock);
335 delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
336 spin_unlock(&clp->cl_lock);
337 rcu_read_unlock();
338 if (delegation)
339 __nfs_inode_return_delegation(inode, delegation);
340 iput(inode);
341 goto restart;
343 rcu_read_unlock();
344 out:
345 nfs_put_client(clp);
346 module_put_and_exit(0);
349 void nfs_expire_all_delegations(struct nfs_client *clp)
351 struct task_struct *task;
353 __module_get(THIS_MODULE);
354 atomic_inc(&clp->cl_count);
355 task = kthread_run(nfs_do_expire_all_delegations, clp,
356 "%s-delegreturn",
357 rpc_peeraddr2str(clp->cl_rpcclient,
358 RPC_DISPLAY_ADDR));
359 if (!IS_ERR(task))
360 return;
361 nfs_put_client(clp);
362 module_put(THIS_MODULE);
366 * Return all delegations following an NFS4ERR_CB_PATH_DOWN error.
368 void nfs_handle_cb_pathdown(struct nfs_client *clp)
370 struct nfs_delegation *delegation;
371 struct inode *inode;
373 if (clp == NULL)
374 return;
375 restart:
376 rcu_read_lock();
377 list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
378 inode = igrab(delegation->inode);
379 if (inode == NULL)
380 continue;
381 spin_lock(&clp->cl_lock);
382 delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
383 spin_unlock(&clp->cl_lock);
384 rcu_read_unlock();
385 if (delegation != NULL)
386 __nfs_inode_return_delegation(inode, delegation);
387 iput(inode);
388 goto restart;
390 rcu_read_unlock();
393 struct recall_threadargs {
394 struct inode *inode;
395 struct nfs_client *clp;
396 const nfs4_stateid *stateid;
398 struct completion started;
399 int result;
402 static int recall_thread(void *data)
404 struct recall_threadargs *args = (struct recall_threadargs *)data;
405 struct inode *inode = igrab(args->inode);
406 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
407 struct nfs_inode *nfsi = NFS_I(inode);
408 struct nfs_delegation *delegation;
410 daemonize("nfsv4-delegreturn");
412 nfs_msync_inode(inode);
413 down_read(&clp->cl_sem);
414 down_write(&nfsi->rwsem);
415 spin_lock(&clp->cl_lock);
416 delegation = nfs_detach_delegation_locked(nfsi, args->stateid);
417 if (delegation != NULL)
418 args->result = 0;
419 else
420 args->result = -ENOENT;
421 spin_unlock(&clp->cl_lock);
422 complete(&args->started);
423 nfs_delegation_claim_opens(inode, args->stateid);
424 up_write(&nfsi->rwsem);
425 up_read(&clp->cl_sem);
426 nfs_msync_inode(inode);
428 if (delegation != NULL)
429 nfs_do_return_delegation(inode, delegation, 1);
430 iput(inode);
431 module_put_and_exit(0);
435 * Asynchronous delegation recall!
437 int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid)
439 struct recall_threadargs data = {
440 .inode = inode,
441 .stateid = stateid,
443 int status;
445 init_completion(&data.started);
446 __module_get(THIS_MODULE);
447 status = kernel_thread(recall_thread, &data, CLONE_KERNEL);
448 if (status < 0)
449 goto out_module_put;
450 wait_for_completion(&data.started);
451 return data.result;
452 out_module_put:
453 module_put(THIS_MODULE);
454 return status;
458 * Retrieve the inode associated with a delegation
460 struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle)
462 struct nfs_delegation *delegation;
463 struct inode *res = NULL;
464 rcu_read_lock();
465 list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
466 if (nfs_compare_fh(fhandle, &NFS_I(delegation->inode)->fh) == 0) {
467 res = igrab(delegation->inode);
468 break;
471 rcu_read_unlock();
472 return res;
476 * Mark all delegations as needing to be reclaimed
478 void nfs_delegation_mark_reclaim(struct nfs_client *clp)
480 struct nfs_delegation *delegation;
481 rcu_read_lock();
482 list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list)
483 delegation->flags |= NFS_DELEGATION_NEED_RECLAIM;
484 rcu_read_unlock();
488 * Reap all unclaimed delegations after reboot recovery is done
490 void nfs_delegation_reap_unclaimed(struct nfs_client *clp)
492 struct nfs_delegation *delegation;
493 restart:
494 rcu_read_lock();
495 list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
496 if ((delegation->flags & NFS_DELEGATION_NEED_RECLAIM) == 0)
497 continue;
498 spin_lock(&clp->cl_lock);
499 delegation = nfs_detach_delegation_locked(NFS_I(delegation->inode), NULL);
500 spin_unlock(&clp->cl_lock);
501 rcu_read_unlock();
502 if (delegation != NULL)
503 nfs_free_delegation(delegation);
504 goto restart;
506 rcu_read_unlock();
509 int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode)
511 struct nfs_inode *nfsi = NFS_I(inode);
512 struct nfs_delegation *delegation;
513 int ret = 0;
515 rcu_read_lock();
516 delegation = rcu_dereference(nfsi->delegation);
517 if (delegation != NULL) {
518 memcpy(dst->data, delegation->stateid.data, sizeof(dst->data));
519 ret = 1;
521 rcu_read_unlock();
522 return ret;