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