]> git.karo-electronics.de Git - karo-tx-linux.git/blob - fs/nfs/delegation.c
NFS: Introduce nfs_detach_delegations()
[karo-tx-linux.git] / fs / nfs / delegation.c
1 /*
2  * linux/fs/nfs/delegation.c
3  *
4  * Copyright (C) 2004 Trond Myklebust
5  *
6  * NFS file delegation management
7  *
8  */
9 #include <linux/completion.h>
10 #include <linux/kthread.h>
11 #include <linux/module.h>
12 #include <linux/sched.h>
13 #include <linux/slab.h>
14 #include <linux/spinlock.h>
15
16 #include <linux/nfs4.h>
17 #include <linux/nfs_fs.h>
18 #include <linux/nfs_xdr.h>
19
20 #include "nfs4_fs.h"
21 #include "delegation.h"
22 #include "internal.h"
23
24 static void nfs_do_free_delegation(struct nfs_delegation *delegation)
25 {
26         if (delegation->cred)
27                 put_rpccred(delegation->cred);
28         kfree(delegation);
29 }
30
31 static void nfs_free_delegation_callback(struct rcu_head *head)
32 {
33         struct nfs_delegation *delegation = container_of(head, struct nfs_delegation, rcu);
34
35         nfs_do_free_delegation(delegation);
36 }
37
38 static void nfs_free_delegation(struct nfs_delegation *delegation)
39 {
40         call_rcu(&delegation->rcu, nfs_free_delegation_callback);
41 }
42
43 void nfs_mark_delegation_referenced(struct nfs_delegation *delegation)
44 {
45         set_bit(NFS_DELEGATION_REFERENCED, &delegation->flags);
46 }
47
48 int nfs_have_delegation(struct inode *inode, fmode_t flags)
49 {
50         struct nfs_delegation *delegation;
51         int ret = 0;
52
53         flags &= FMODE_READ|FMODE_WRITE;
54         rcu_read_lock();
55         delegation = rcu_dereference(NFS_I(inode)->delegation);
56         if (delegation != NULL && (delegation->type & flags) == flags) {
57                 nfs_mark_delegation_referenced(delegation);
58                 ret = 1;
59         }
60         rcu_read_unlock();
61         return ret;
62 }
63
64 static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_state *state)
65 {
66         struct inode *inode = state->inode;
67         struct file_lock *fl;
68         int status = 0;
69
70         if (inode->i_flock == NULL)
71                 goto out;
72
73         /* Protect inode->i_flock using the file locks lock */
74         lock_flocks();
75         for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
76                 if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
77                         continue;
78                 if (nfs_file_open_context(fl->fl_file) != ctx)
79                         continue;
80                 unlock_flocks();
81                 status = nfs4_lock_delegation_recall(state, fl);
82                 if (status < 0)
83                         goto out;
84                 lock_flocks();
85         }
86         unlock_flocks();
87 out:
88         return status;
89 }
90
91 static int nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *stateid)
92 {
93         struct nfs_inode *nfsi = NFS_I(inode);
94         struct nfs_open_context *ctx;
95         struct nfs4_state *state;
96         int err;
97
98 again:
99         spin_lock(&inode->i_lock);
100         list_for_each_entry(ctx, &nfsi->open_files, list) {
101                 state = ctx->state;
102                 if (state == NULL)
103                         continue;
104                 if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
105                         continue;
106                 if (memcmp(state->stateid.data, stateid->data, sizeof(state->stateid.data)) != 0)
107                         continue;
108                 get_nfs_open_context(ctx);
109                 spin_unlock(&inode->i_lock);
110                 err = nfs4_open_delegation_recall(ctx, state, stateid);
111                 if (err >= 0)
112                         err = nfs_delegation_claim_locks(ctx, state);
113                 put_nfs_open_context(ctx);
114                 if (err != 0)
115                         return err;
116                 goto again;
117         }
118         spin_unlock(&inode->i_lock);
119         return 0;
120 }
121
122 /*
123  * Set up a delegation on an inode
124  */
125 void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res)
126 {
127         struct nfs_delegation *delegation;
128         struct rpc_cred *oldcred = NULL;
129
130         rcu_read_lock();
131         delegation = rcu_dereference(NFS_I(inode)->delegation);
132         if (delegation != NULL) {
133                 spin_lock(&delegation->lock);
134                 if (delegation->inode != NULL) {
135                         memcpy(delegation->stateid.data, res->delegation.data,
136                                sizeof(delegation->stateid.data));
137                         delegation->type = res->delegation_type;
138                         delegation->maxsize = res->maxsize;
139                         oldcred = delegation->cred;
140                         delegation->cred = get_rpccred(cred);
141                         clear_bit(NFS_DELEGATION_NEED_RECLAIM,
142                                   &delegation->flags);
143                         NFS_I(inode)->delegation_state = delegation->type;
144                         spin_unlock(&delegation->lock);
145                         put_rpccred(oldcred);
146                         rcu_read_unlock();
147                 } else {
148                         /* We appear to have raced with a delegation return. */
149                         spin_unlock(&delegation->lock);
150                         rcu_read_unlock();
151                         nfs_inode_set_delegation(inode, cred, res);
152                 }
153         } else {
154                 rcu_read_unlock();
155         }
156 }
157
158 static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync)
159 {
160         int res = 0;
161
162         res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid, issync);
163         nfs_free_delegation(delegation);
164         return res;
165 }
166
167 static struct inode *nfs_delegation_grab_inode(struct nfs_delegation *delegation)
168 {
169         struct inode *inode = NULL;
170
171         spin_lock(&delegation->lock);
172         if (delegation->inode != NULL)
173                 inode = igrab(delegation->inode);
174         spin_unlock(&delegation->lock);
175         return inode;
176 }
177
178 static struct nfs_delegation *
179 nfs_detach_delegation_locked(struct nfs_inode *nfsi,
180                              struct nfs_client *clp)
181 {
182         struct nfs_delegation *delegation =
183                 rcu_dereference_protected(nfsi->delegation,
184                                           lockdep_is_held(&clp->cl_lock));
185
186         if (delegation == NULL)
187                 goto nomatch;
188
189         spin_lock(&delegation->lock);
190         list_del_rcu(&delegation->super_list);
191         delegation->inode = NULL;
192         nfsi->delegation_state = 0;
193         rcu_assign_pointer(nfsi->delegation, NULL);
194         spin_unlock(&delegation->lock);
195         return delegation;
196 nomatch:
197         return NULL;
198 }
199
200 static struct nfs_delegation *nfs_detach_delegation(struct nfs_inode *nfsi,
201                                                     struct nfs_client *clp)
202 {
203         struct nfs_delegation *delegation;
204
205         spin_lock(&clp->cl_lock);
206         delegation = nfs_detach_delegation_locked(nfsi, clp);
207         spin_unlock(&clp->cl_lock);
208         return delegation;
209 }
210
211 /*
212  * Set up a delegation on an inode
213  */
214 int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res)
215 {
216         struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
217         struct nfs_inode *nfsi = NFS_I(inode);
218         struct nfs_delegation *delegation, *old_delegation;
219         struct nfs_delegation *freeme = NULL;
220         int status = 0;
221
222         delegation = kmalloc(sizeof(*delegation), GFP_NOFS);
223         if (delegation == NULL)
224                 return -ENOMEM;
225         memcpy(delegation->stateid.data, res->delegation.data,
226                         sizeof(delegation->stateid.data));
227         delegation->type = res->delegation_type;
228         delegation->maxsize = res->maxsize;
229         delegation->change_attr = nfsi->change_attr;
230         delegation->cred = get_rpccred(cred);
231         delegation->inode = inode;
232         delegation->flags = 1<<NFS_DELEGATION_REFERENCED;
233         spin_lock_init(&delegation->lock);
234
235         spin_lock(&clp->cl_lock);
236         old_delegation = rcu_dereference_protected(nfsi->delegation,
237                                                    lockdep_is_held(&clp->cl_lock));
238         if (old_delegation != NULL) {
239                 if (memcmp(&delegation->stateid, &old_delegation->stateid,
240                                         sizeof(old_delegation->stateid)) == 0 &&
241                                 delegation->type == old_delegation->type) {
242                         goto out;
243                 }
244                 /*
245                  * Deal with broken servers that hand out two
246                  * delegations for the same file.
247                  */
248                 dfprintk(FILE, "%s: server %s handed out "
249                                 "a duplicate delegation!\n",
250                                 __func__, clp->cl_hostname);
251                 if (delegation->type <= old_delegation->type) {
252                         freeme = delegation;
253                         delegation = NULL;
254                         goto out;
255                 }
256                 freeme = nfs_detach_delegation_locked(nfsi, clp);
257         }
258         list_add_rcu(&delegation->super_list, &clp->cl_delegations);
259         nfsi->delegation_state = delegation->type;
260         rcu_assign_pointer(nfsi->delegation, delegation);
261         delegation = NULL;
262
263         /* Ensure we revalidate the attributes and page cache! */
264         spin_lock(&inode->i_lock);
265         nfsi->cache_validity |= NFS_INO_REVAL_FORCED;
266         spin_unlock(&inode->i_lock);
267
268 out:
269         spin_unlock(&clp->cl_lock);
270         if (delegation != NULL)
271                 nfs_free_delegation(delegation);
272         if (freeme != NULL)
273                 nfs_do_return_delegation(inode, freeme, 0);
274         return status;
275 }
276
277 /*
278  * Basic procedure for returning a delegation to the server
279  */
280 static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync)
281 {
282         struct nfs_inode *nfsi = NFS_I(inode);
283         int err;
284
285         /*
286          * Guard against new delegated open/lock/unlock calls and against
287          * state recovery
288          */
289         down_write(&nfsi->rwsem);
290         err = nfs_delegation_claim_opens(inode, &delegation->stateid);
291         up_write(&nfsi->rwsem);
292         if (err)
293                 goto out;
294
295         err = nfs_do_return_delegation(inode, delegation, issync);
296 out:
297         return err;
298 }
299
300 /*
301  * Return all delegations that have been marked for return
302  */
303 int nfs_client_return_marked_delegations(struct nfs_client *clp)
304 {
305         struct nfs_delegation *delegation;
306         struct inode *inode;
307         int err = 0;
308
309 restart:
310         rcu_read_lock();
311         list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
312                 if (!test_and_clear_bit(NFS_DELEGATION_RETURN, &delegation->flags))
313                         continue;
314                 inode = nfs_delegation_grab_inode(delegation);
315                 if (inode == NULL)
316                         continue;
317                 delegation = nfs_detach_delegation(NFS_I(inode), clp);
318                 rcu_read_unlock();
319                 if (delegation != NULL) {
320                         filemap_flush(inode->i_mapping);
321                         err = __nfs_inode_return_delegation(inode, delegation, 0);
322                 }
323                 iput(inode);
324                 if (!err)
325                         goto restart;
326                 set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
327                 return err;
328         }
329         rcu_read_unlock();
330         return 0;
331 }
332
333 /*
334  * This function returns the delegation without reclaiming opens
335  * or protecting against delegation reclaims.
336  * It is therefore really only safe to be called from
337  * nfs4_clear_inode()
338  */
339 void nfs_inode_return_delegation_noreclaim(struct inode *inode)
340 {
341         struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
342         struct nfs_inode *nfsi = NFS_I(inode);
343         struct nfs_delegation *delegation;
344
345         if (rcu_access_pointer(nfsi->delegation) != NULL) {
346                 delegation = nfs_detach_delegation(nfsi, clp);
347                 if (delegation != NULL)
348                         nfs_do_return_delegation(inode, delegation, 0);
349         }
350 }
351
352 int nfs_inode_return_delegation(struct inode *inode)
353 {
354         struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
355         struct nfs_inode *nfsi = NFS_I(inode);
356         struct nfs_delegation *delegation;
357         int err = 0;
358
359         if (rcu_access_pointer(nfsi->delegation) != NULL) {
360                 delegation = nfs_detach_delegation(nfsi, clp);
361                 if (delegation != NULL) {
362                         nfs_wb_all(inode);
363                         err = __nfs_inode_return_delegation(inode, delegation, 1);
364                 }
365         }
366         return err;
367 }
368
369 static void nfs_mark_return_delegation(struct nfs_client *clp, struct nfs_delegation *delegation)
370 {
371         set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
372         set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
373 }
374
375 /*
376  * Return all delegations associated to a super block
377  */
378 void nfs_super_return_all_delegations(struct super_block *sb)
379 {
380         struct nfs_client *clp = NFS_SB(sb)->nfs_client;
381         struct nfs_delegation *delegation;
382
383         if (clp == NULL)
384                 return;
385         rcu_read_lock();
386         list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
387                 spin_lock(&delegation->lock);
388                 if (delegation->inode != NULL && delegation->inode->i_sb == sb)
389                         set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
390                 spin_unlock(&delegation->lock);
391         }
392         rcu_read_unlock();
393         if (nfs_client_return_marked_delegations(clp) != 0)
394                 nfs4_schedule_state_manager(clp);
395 }
396
397 static
398 void nfs_client_mark_return_all_delegation_types(struct nfs_client *clp, fmode_t flags)
399 {
400         struct nfs_delegation *delegation;
401
402         rcu_read_lock();
403         list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
404                 if ((delegation->type == (FMODE_READ|FMODE_WRITE)) && !(flags & FMODE_WRITE))
405                         continue;
406                 if (delegation->type & flags)
407                         nfs_mark_return_delegation(clp, delegation);
408         }
409         rcu_read_unlock();
410 }
411
412 static void nfs_client_mark_return_all_delegations(struct nfs_client *clp)
413 {
414         nfs_client_mark_return_all_delegation_types(clp, FMODE_READ|FMODE_WRITE);
415 }
416
417 static void nfs_delegation_run_state_manager(struct nfs_client *clp)
418 {
419         if (test_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state))
420                 nfs4_schedule_state_manager(clp);
421 }
422
423 void nfs_expire_all_delegation_types(struct nfs_client *clp, fmode_t flags)
424 {
425         nfs_client_mark_return_all_delegation_types(clp, flags);
426         nfs_delegation_run_state_manager(clp);
427 }
428
429 void nfs_expire_all_delegations(struct nfs_client *clp)
430 {
431         nfs_expire_all_delegation_types(clp, FMODE_READ|FMODE_WRITE);
432 }
433
434 /*
435  * Return all delegations following an NFS4ERR_CB_PATH_DOWN error.
436  */
437 void nfs_handle_cb_pathdown(struct nfs_client *clp)
438 {
439         if (clp == NULL)
440                 return;
441         nfs_client_mark_return_all_delegations(clp);
442 }
443
444 static void nfs_client_mark_return_unreferenced_delegations(struct nfs_client *clp)
445 {
446         struct nfs_delegation *delegation;
447
448         rcu_read_lock();
449         list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
450                 if (test_and_clear_bit(NFS_DELEGATION_REFERENCED, &delegation->flags))
451                         continue;
452                 nfs_mark_return_delegation(clp, delegation);
453         }
454         rcu_read_unlock();
455 }
456
457 void nfs_expire_unreferenced_delegations(struct nfs_client *clp)
458 {
459         nfs_client_mark_return_unreferenced_delegations(clp);
460         nfs_delegation_run_state_manager(clp);
461 }
462
463 /*
464  * Asynchronous delegation recall!
465  */
466 int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid)
467 {
468         struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
469         struct nfs_delegation *delegation;
470
471         rcu_read_lock();
472         delegation = rcu_dereference(NFS_I(inode)->delegation);
473
474         if (!clp->cl_mvops->validate_stateid(delegation, stateid)) {
475                 rcu_read_unlock();
476                 return -ENOENT;
477         }
478
479         nfs_mark_return_delegation(clp, delegation);
480         rcu_read_unlock();
481         nfs_delegation_run_state_manager(clp);
482         return 0;
483 }
484
485 /*
486  * Retrieve the inode associated with a delegation
487  */
488 struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle)
489 {
490         struct nfs_delegation *delegation;
491         struct inode *res = NULL;
492         rcu_read_lock();
493         list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
494                 spin_lock(&delegation->lock);
495                 if (delegation->inode != NULL &&
496                     nfs_compare_fh(fhandle, &NFS_I(delegation->inode)->fh) == 0) {
497                         res = igrab(delegation->inode);
498                 }
499                 spin_unlock(&delegation->lock);
500                 if (res != NULL)
501                         break;
502         }
503         rcu_read_unlock();
504         return res;
505 }
506
507 /*
508  * Mark all delegations as needing to be reclaimed
509  */
510 void nfs_delegation_mark_reclaim(struct nfs_client *clp)
511 {
512         struct nfs_delegation *delegation;
513         rcu_read_lock();
514         list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list)
515                 set_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags);
516         rcu_read_unlock();
517 }
518
519 /*
520  * Reap all unclaimed delegations after reboot recovery is done
521  */
522 void nfs_delegation_reap_unclaimed(struct nfs_client *clp)
523 {
524         struct nfs_delegation *delegation;
525         struct inode *inode;
526 restart:
527         rcu_read_lock();
528         list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
529                 if (test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags) == 0)
530                         continue;
531                 inode = nfs_delegation_grab_inode(delegation);
532                 if (inode == NULL)
533                         continue;
534                 delegation = nfs_detach_delegation(NFS_I(inode), clp);
535                 rcu_read_unlock();
536                 if (delegation != NULL)
537                         nfs_free_delegation(delegation);
538                 iput(inode);
539                 goto restart;
540         }
541         rcu_read_unlock();
542 }
543
544 int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode)
545 {
546         struct nfs_inode *nfsi = NFS_I(inode);
547         struct nfs_delegation *delegation;
548         int ret = 0;
549
550         rcu_read_lock();
551         delegation = rcu_dereference(nfsi->delegation);
552         if (delegation != NULL) {
553                 memcpy(dst->data, delegation->stateid.data, sizeof(dst->data));
554                 ret = 1;
555         }
556         rcu_read_unlock();
557         return ret;
558 }