aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/delegation.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /fs/nfs/delegation.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'fs/nfs/delegation.c')
-rw-r--r--fs/nfs/delegation.c393
1 files changed, 269 insertions, 124 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index b9c3c43cea1d..dd25c2aec375 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -11,7 +11,6 @@
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/sched.h> 12#include <linux/sched.h>
13#include <linux/slab.h> 13#include <linux/slab.h>
14#include <linux/smp_lock.h>
15#include <linux/spinlock.h> 14#include <linux/spinlock.h>
16 15
17#include <linux/nfs4.h> 16#include <linux/nfs4.h>
@@ -22,30 +21,32 @@
22#include "delegation.h" 21#include "delegation.h"
23#include "internal.h" 22#include "internal.h"
24 23
25static void nfs_do_free_delegation(struct nfs_delegation *delegation)
26{
27 if (delegation->cred)
28 put_rpccred(delegation->cred);
29 kfree(delegation);
30}
31
32static void nfs_free_delegation_callback(struct rcu_head *head)
33{
34 struct nfs_delegation *delegation = container_of(head, struct nfs_delegation, rcu);
35
36 nfs_do_free_delegation(delegation);
37}
38
39static void nfs_free_delegation(struct nfs_delegation *delegation) 24static void nfs_free_delegation(struct nfs_delegation *delegation)
40{ 25{
41 call_rcu(&delegation->rcu, nfs_free_delegation_callback); 26 if (delegation->cred) {
27 put_rpccred(delegation->cred);
28 delegation->cred = NULL;
29 }
30 kfree_rcu(delegation, rcu);
42} 31}
43 32
33/**
34 * nfs_mark_delegation_referenced - set delegation's REFERENCED flag
35 * @delegation: delegation to process
36 *
37 */
44void nfs_mark_delegation_referenced(struct nfs_delegation *delegation) 38void nfs_mark_delegation_referenced(struct nfs_delegation *delegation)
45{ 39{
46 set_bit(NFS_DELEGATION_REFERENCED, &delegation->flags); 40 set_bit(NFS_DELEGATION_REFERENCED, &delegation->flags);
47} 41}
48 42
43/**
44 * nfs_have_delegation - check if inode has a delegation
45 * @inode: inode to check
46 * @flags: delegation types to check for
47 *
48 * Returns one if inode has the indicated delegation, otherwise zero.
49 */
49int nfs_have_delegation(struct inode *inode, fmode_t flags) 50int nfs_have_delegation(struct inode *inode, fmode_t flags)
50{ 51{
51 struct nfs_delegation *delegation; 52 struct nfs_delegation *delegation;
@@ -71,20 +72,20 @@ static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_
71 if (inode->i_flock == NULL) 72 if (inode->i_flock == NULL)
72 goto out; 73 goto out;
73 74
74 /* Protect inode->i_flock using the BKL */ 75 /* Protect inode->i_flock using the file locks lock */
75 lock_kernel(); 76 lock_flocks();
76 for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { 77 for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
77 if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK))) 78 if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
78 continue; 79 continue;
79 if (nfs_file_open_context(fl->fl_file) != ctx) 80 if (nfs_file_open_context(fl->fl_file) != ctx)
80 continue; 81 continue;
81 unlock_kernel(); 82 unlock_flocks();
82 status = nfs4_lock_delegation_recall(state, fl); 83 status = nfs4_lock_delegation_recall(state, fl);
83 if (status < 0) 84 if (status < 0)
84 goto out; 85 goto out;
85 lock_kernel(); 86 lock_flocks();
86 } 87 }
87 unlock_kernel(); 88 unlock_flocks();
88out: 89out:
89 return status; 90 return status;
90} 91}
@@ -120,10 +121,15 @@ again:
120 return 0; 121 return 0;
121} 122}
122 123
123/* 124/**
124 * Set up a delegation on an inode 125 * nfs_inode_reclaim_delegation - process a delegation reclaim request
126 * @inode: inode to process
127 * @cred: credential to use for request
128 * @res: new delegation state from server
129 *
125 */ 130 */
126void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res) 131void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred,
132 struct nfs_openres *res)
127{ 133{
128 struct nfs_delegation *delegation; 134 struct nfs_delegation *delegation;
129 struct rpc_cred *oldcred = NULL; 135 struct rpc_cred *oldcred = NULL;
@@ -176,38 +182,52 @@ static struct inode *nfs_delegation_grab_inode(struct nfs_delegation *delegation
176 return inode; 182 return inode;
177} 183}
178 184
179static struct nfs_delegation *nfs_detach_delegation_locked(struct nfs_inode *nfsi, 185static struct nfs_delegation *
180 const nfs4_stateid *stateid, 186nfs_detach_delegation_locked(struct nfs_inode *nfsi,
181 struct nfs_client *clp) 187 struct nfs_server *server)
182{ 188{
183 struct nfs_delegation *delegation = 189 struct nfs_delegation *delegation =
184 rcu_dereference_protected(nfsi->delegation, 190 rcu_dereference_protected(nfsi->delegation,
185 lockdep_is_held(&clp->cl_lock)); 191 lockdep_is_held(&server->nfs_client->cl_lock));
186 192
187 if (delegation == NULL) 193 if (delegation == NULL)
188 goto nomatch; 194 goto nomatch;
195
189 spin_lock(&delegation->lock); 196 spin_lock(&delegation->lock);
190 if (stateid != NULL && memcmp(delegation->stateid.data, stateid->data,
191 sizeof(delegation->stateid.data)) != 0)
192 goto nomatch_unlock;
193 list_del_rcu(&delegation->super_list); 197 list_del_rcu(&delegation->super_list);
194 delegation->inode = NULL; 198 delegation->inode = NULL;
195 nfsi->delegation_state = 0; 199 nfsi->delegation_state = 0;
196 rcu_assign_pointer(nfsi->delegation, NULL); 200 rcu_assign_pointer(nfsi->delegation, NULL);
197 spin_unlock(&delegation->lock); 201 spin_unlock(&delegation->lock);
198 return delegation; 202 return delegation;
199nomatch_unlock:
200 spin_unlock(&delegation->lock);
201nomatch: 203nomatch:
202 return NULL; 204 return NULL;
203} 205}
204 206
205/* 207static struct nfs_delegation *nfs_detach_delegation(struct nfs_inode *nfsi,
206 * Set up a delegation on an inode 208 struct nfs_server *server)
209{
210 struct nfs_client *clp = server->nfs_client;
211 struct nfs_delegation *delegation;
212
213 spin_lock(&clp->cl_lock);
214 delegation = nfs_detach_delegation_locked(nfsi, server);
215 spin_unlock(&clp->cl_lock);
216 return delegation;
217}
218
219/**
220 * nfs_inode_set_delegation - set up a delegation on an inode
221 * @inode: inode to which delegation applies
222 * @cred: cred to use for subsequent delegation processing
223 * @res: new delegation state from server
224 *
225 * Returns zero on success, or a negative errno value.
207 */ 226 */
208int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res) 227int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res)
209{ 228{
210 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; 229 struct nfs_server *server = NFS_SERVER(inode);
230 struct nfs_client *clp = server->nfs_client;
211 struct nfs_inode *nfsi = NFS_I(inode); 231 struct nfs_inode *nfsi = NFS_I(inode);
212 struct nfs_delegation *delegation, *old_delegation; 232 struct nfs_delegation *delegation, *old_delegation;
213 struct nfs_delegation *freeme = NULL; 233 struct nfs_delegation *freeme = NULL;
@@ -228,7 +248,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
228 248
229 spin_lock(&clp->cl_lock); 249 spin_lock(&clp->cl_lock);
230 old_delegation = rcu_dereference_protected(nfsi->delegation, 250 old_delegation = rcu_dereference_protected(nfsi->delegation,
231 lockdep_is_held(&clp->cl_lock)); 251 lockdep_is_held(&clp->cl_lock));
232 if (old_delegation != NULL) { 252 if (old_delegation != NULL) {
233 if (memcmp(&delegation->stateid, &old_delegation->stateid, 253 if (memcmp(&delegation->stateid, &old_delegation->stateid,
234 sizeof(old_delegation->stateid)) == 0 && 254 sizeof(old_delegation->stateid)) == 0 &&
@@ -247,9 +267,9 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
247 delegation = NULL; 267 delegation = NULL;
248 goto out; 268 goto out;
249 } 269 }
250 freeme = nfs_detach_delegation_locked(nfsi, NULL, clp); 270 freeme = nfs_detach_delegation_locked(nfsi, server);
251 } 271 }
252 list_add_rcu(&delegation->super_list, &clp->cl_delegations); 272 list_add_rcu(&delegation->super_list, &server->delegations);
253 nfsi->delegation_state = delegation->type; 273 nfsi->delegation_state = delegation->type;
254 rcu_assign_pointer(nfsi->delegation, delegation); 274 rcu_assign_pointer(nfsi->delegation, delegation);
255 delegation = NULL; 275 delegation = NULL;
@@ -291,73 +311,85 @@ out:
291 return err; 311 return err;
292} 312}
293 313
294/* 314/**
295 * Return all delegations that have been marked for return 315 * nfs_client_return_marked_delegations - return previously marked delegations
316 * @clp: nfs_client to process
317 *
318 * Returns zero on success, or a negative errno value.
296 */ 319 */
297int nfs_client_return_marked_delegations(struct nfs_client *clp) 320int nfs_client_return_marked_delegations(struct nfs_client *clp)
298{ 321{
299 struct nfs_delegation *delegation; 322 struct nfs_delegation *delegation;
323 struct nfs_server *server;
300 struct inode *inode; 324 struct inode *inode;
301 int err = 0; 325 int err = 0;
302 326
303restart: 327restart:
304 rcu_read_lock(); 328 rcu_read_lock();
305 list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) { 329 list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
306 if (!test_and_clear_bit(NFS_DELEGATION_RETURN, &delegation->flags)) 330 list_for_each_entry_rcu(delegation, &server->delegations,
307 continue; 331 super_list) {
308 inode = nfs_delegation_grab_inode(delegation); 332 if (!test_and_clear_bit(NFS_DELEGATION_RETURN,
309 if (inode == NULL) 333 &delegation->flags))
310 continue; 334 continue;
311 spin_lock(&clp->cl_lock); 335 inode = nfs_delegation_grab_inode(delegation);
312 delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL, clp); 336 if (inode == NULL)
313 spin_unlock(&clp->cl_lock); 337 continue;
314 rcu_read_unlock(); 338 delegation = nfs_detach_delegation(NFS_I(inode),
315 if (delegation != NULL) { 339 server);
316 filemap_flush(inode->i_mapping); 340 rcu_read_unlock();
317 err = __nfs_inode_return_delegation(inode, delegation, 0); 341
342 if (delegation != NULL) {
343 filemap_flush(inode->i_mapping);
344 err = __nfs_inode_return_delegation(inode,
345 delegation, 0);
346 }
347 iput(inode);
348 if (!err)
349 goto restart;
350 set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
351 return err;
318 } 352 }
319 iput(inode);
320 if (!err)
321 goto restart;
322 set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
323 return err;
324 } 353 }
325 rcu_read_unlock(); 354 rcu_read_unlock();
326 return 0; 355 return 0;
327} 356}
328 357
329/* 358/**
330 * This function returns the delegation without reclaiming opens 359 * nfs_inode_return_delegation_noreclaim - return delegation, don't reclaim opens
331 * or protecting against delegation reclaims. 360 * @inode: inode to process
332 * It is therefore really only safe to be called from 361 *
333 * nfs4_clear_inode() 362 * Does not protect against delegation reclaims, therefore really only safe
363 * to be called from nfs4_clear_inode().
334 */ 364 */
335void nfs_inode_return_delegation_noreclaim(struct inode *inode) 365void nfs_inode_return_delegation_noreclaim(struct inode *inode)
336{ 366{
337 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; 367 struct nfs_server *server = NFS_SERVER(inode);
338 struct nfs_inode *nfsi = NFS_I(inode); 368 struct nfs_inode *nfsi = NFS_I(inode);
339 struct nfs_delegation *delegation; 369 struct nfs_delegation *delegation;
340 370
341 if (rcu_access_pointer(nfsi->delegation) != NULL) { 371 if (rcu_access_pointer(nfsi->delegation) != NULL) {
342 spin_lock(&clp->cl_lock); 372 delegation = nfs_detach_delegation(nfsi, server);
343 delegation = nfs_detach_delegation_locked(nfsi, NULL, clp);
344 spin_unlock(&clp->cl_lock);
345 if (delegation != NULL) 373 if (delegation != NULL)
346 nfs_do_return_delegation(inode, delegation, 0); 374 nfs_do_return_delegation(inode, delegation, 0);
347 } 375 }
348} 376}
349 377
378/**
379 * nfs_inode_return_delegation - synchronously return a delegation
380 * @inode: inode to process
381 *
382 * Returns zero on success, or a negative errno value.
383 */
350int nfs_inode_return_delegation(struct inode *inode) 384int nfs_inode_return_delegation(struct inode *inode)
351{ 385{
352 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; 386 struct nfs_server *server = NFS_SERVER(inode);
353 struct nfs_inode *nfsi = NFS_I(inode); 387 struct nfs_inode *nfsi = NFS_I(inode);
354 struct nfs_delegation *delegation; 388 struct nfs_delegation *delegation;
355 int err = 0; 389 int err = 0;
356 390
357 if (rcu_access_pointer(nfsi->delegation) != NULL) { 391 if (rcu_access_pointer(nfsi->delegation) != NULL) {
358 spin_lock(&clp->cl_lock); 392 delegation = nfs_detach_delegation(nfsi, server);
359 delegation = nfs_detach_delegation_locked(nfsi, NULL, clp);
360 spin_unlock(&clp->cl_lock);
361 if (delegation != NULL) { 393 if (delegation != NULL) {
362 nfs_wb_all(inode); 394 nfs_wb_all(inode);
363 err = __nfs_inode_return_delegation(inode, delegation, 1); 395 err = __nfs_inode_return_delegation(inode, delegation, 1);
@@ -366,46 +398,61 @@ int nfs_inode_return_delegation(struct inode *inode)
366 return err; 398 return err;
367} 399}
368 400
369static void nfs_mark_return_delegation(struct nfs_client *clp, struct nfs_delegation *delegation) 401static void nfs_mark_return_delegation(struct nfs_delegation *delegation)
370{ 402{
403 struct nfs_client *clp = NFS_SERVER(delegation->inode)->nfs_client;
404
371 set_bit(NFS_DELEGATION_RETURN, &delegation->flags); 405 set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
372 set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state); 406 set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
373} 407}
374 408
375/* 409/**
376 * Return all delegations associated to a super block 410 * nfs_super_return_all_delegations - return delegations for one superblock
411 * @sb: sb to process
412 *
377 */ 413 */
378void nfs_super_return_all_delegations(struct super_block *sb) 414void nfs_super_return_all_delegations(struct super_block *sb)
379{ 415{
380 struct nfs_client *clp = NFS_SB(sb)->nfs_client; 416 struct nfs_server *server = NFS_SB(sb);
417 struct nfs_client *clp = server->nfs_client;
381 struct nfs_delegation *delegation; 418 struct nfs_delegation *delegation;
382 419
383 if (clp == NULL) 420 if (clp == NULL)
384 return; 421 return;
422
385 rcu_read_lock(); 423 rcu_read_lock();
386 list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) { 424 list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
387 spin_lock(&delegation->lock); 425 spin_lock(&delegation->lock);
388 if (delegation->inode != NULL && delegation->inode->i_sb == sb) 426 set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
389 set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
390 spin_unlock(&delegation->lock); 427 spin_unlock(&delegation->lock);
391 } 428 }
392 rcu_read_unlock(); 429 rcu_read_unlock();
430
393 if (nfs_client_return_marked_delegations(clp) != 0) 431 if (nfs_client_return_marked_delegations(clp) != 0)
394 nfs4_schedule_state_manager(clp); 432 nfs4_schedule_state_manager(clp);
395} 433}
396 434
397static 435static void nfs_mark_return_all_delegation_types(struct nfs_server *server,
398void nfs_client_mark_return_all_delegation_types(struct nfs_client *clp, fmode_t flags) 436 fmode_t flags)
399{ 437{
400 struct nfs_delegation *delegation; 438 struct nfs_delegation *delegation;
401 439
402 rcu_read_lock(); 440 list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
403 list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
404 if ((delegation->type == (FMODE_READ|FMODE_WRITE)) && !(flags & FMODE_WRITE)) 441 if ((delegation->type == (FMODE_READ|FMODE_WRITE)) && !(flags & FMODE_WRITE))
405 continue; 442 continue;
406 if (delegation->type & flags) 443 if (delegation->type & flags)
407 nfs_mark_return_delegation(clp, delegation); 444 nfs_mark_return_delegation(delegation);
408 } 445 }
446}
447
448static void nfs_client_mark_return_all_delegation_types(struct nfs_client *clp,
449 fmode_t flags)
450{
451 struct nfs_server *server;
452
453 rcu_read_lock();
454 list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
455 nfs_mark_return_all_delegation_types(server, flags);
409 rcu_read_unlock(); 456 rcu_read_unlock();
410} 457}
411 458
@@ -420,19 +467,32 @@ static void nfs_delegation_run_state_manager(struct nfs_client *clp)
420 nfs4_schedule_state_manager(clp); 467 nfs4_schedule_state_manager(clp);
421} 468}
422 469
470/**
471 * nfs_expire_all_delegation_types
472 * @clp: client to process
473 * @flags: delegation types to expire
474 *
475 */
423void nfs_expire_all_delegation_types(struct nfs_client *clp, fmode_t flags) 476void nfs_expire_all_delegation_types(struct nfs_client *clp, fmode_t flags)
424{ 477{
425 nfs_client_mark_return_all_delegation_types(clp, flags); 478 nfs_client_mark_return_all_delegation_types(clp, flags);
426 nfs_delegation_run_state_manager(clp); 479 nfs_delegation_run_state_manager(clp);
427} 480}
428 481
482/**
483 * nfs_expire_all_delegations
484 * @clp: client to process
485 *
486 */
429void nfs_expire_all_delegations(struct nfs_client *clp) 487void nfs_expire_all_delegations(struct nfs_client *clp)
430{ 488{
431 nfs_expire_all_delegation_types(clp, FMODE_READ|FMODE_WRITE); 489 nfs_expire_all_delegation_types(clp, FMODE_READ|FMODE_WRITE);
432} 490}
433 491
434/* 492/**
435 * Return all delegations following an NFS4ERR_CB_PATH_DOWN error. 493 * nfs_handle_cb_pathdown - return all delegations after NFS4ERR_CB_PATH_DOWN
494 * @clp: client to process
495 *
436 */ 496 */
437void nfs_handle_cb_pathdown(struct nfs_client *clp) 497void nfs_handle_cb_pathdown(struct nfs_client *clp)
438{ 498{
@@ -441,29 +501,43 @@ void nfs_handle_cb_pathdown(struct nfs_client *clp)
441 nfs_client_mark_return_all_delegations(clp); 501 nfs_client_mark_return_all_delegations(clp);
442} 502}
443 503
444static void nfs_client_mark_return_unreferenced_delegations(struct nfs_client *clp) 504static void nfs_mark_return_unreferenced_delegations(struct nfs_server *server)
445{ 505{
446 struct nfs_delegation *delegation; 506 struct nfs_delegation *delegation;
447 507
448 rcu_read_lock(); 508 list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
449 list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
450 if (test_and_clear_bit(NFS_DELEGATION_REFERENCED, &delegation->flags)) 509 if (test_and_clear_bit(NFS_DELEGATION_REFERENCED, &delegation->flags))
451 continue; 510 continue;
452 nfs_mark_return_delegation(clp, delegation); 511 nfs_mark_return_delegation(delegation);
453 } 512 }
454 rcu_read_unlock();
455} 513}
456 514
515/**
516 * nfs_expire_unreferenced_delegations - Eliminate unused delegations
517 * @clp: nfs_client to process
518 *
519 */
457void nfs_expire_unreferenced_delegations(struct nfs_client *clp) 520void nfs_expire_unreferenced_delegations(struct nfs_client *clp)
458{ 521{
459 nfs_client_mark_return_unreferenced_delegations(clp); 522 struct nfs_server *server;
523
524 rcu_read_lock();
525 list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
526 nfs_mark_return_unreferenced_delegations(server);
527 rcu_read_unlock();
528
460 nfs_delegation_run_state_manager(clp); 529 nfs_delegation_run_state_manager(clp);
461} 530}
462 531
463/* 532/**
464 * Asynchronous delegation recall! 533 * nfs_async_inode_return_delegation - asynchronously return a delegation
534 * @inode: inode to process
535 * @stateid: state ID information from CB_RECALL arguments
536 *
537 * Returns zero on success, or a negative errno value.
465 */ 538 */
466int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid) 539int nfs_async_inode_return_delegation(struct inode *inode,
540 const nfs4_stateid *stateid)
467{ 541{
468 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; 542 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
469 struct nfs_delegation *delegation; 543 struct nfs_delegation *delegation;
@@ -475,22 +549,21 @@ int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *s
475 rcu_read_unlock(); 549 rcu_read_unlock();
476 return -ENOENT; 550 return -ENOENT;
477 } 551 }
478 552 nfs_mark_return_delegation(delegation);
479 nfs_mark_return_delegation(clp, delegation);
480 rcu_read_unlock(); 553 rcu_read_unlock();
554
481 nfs_delegation_run_state_manager(clp); 555 nfs_delegation_run_state_manager(clp);
482 return 0; 556 return 0;
483} 557}
484 558
485/* 559static struct inode *
486 * Retrieve the inode associated with a delegation 560nfs_delegation_find_inode_server(struct nfs_server *server,
487 */ 561 const struct nfs_fh *fhandle)
488struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle)
489{ 562{
490 struct nfs_delegation *delegation; 563 struct nfs_delegation *delegation;
491 struct inode *res = NULL; 564 struct inode *res = NULL;
492 rcu_read_lock(); 565
493 list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) { 566 list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
494 spin_lock(&delegation->lock); 567 spin_lock(&delegation->lock);
495 if (delegation->inode != NULL && 568 if (delegation->inode != NULL &&
496 nfs_compare_fh(fhandle, &NFS_I(delegation->inode)->fh) == 0) { 569 nfs_compare_fh(fhandle, &NFS_I(delegation->inode)->fh) == 0) {
@@ -500,49 +573,121 @@ struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs
500 if (res != NULL) 573 if (res != NULL)
501 break; 574 break;
502 } 575 }
576 return res;
577}
578
579/**
580 * nfs_delegation_find_inode - retrieve the inode associated with a delegation
581 * @clp: client state handle
582 * @fhandle: filehandle from a delegation recall
583 *
584 * Returns pointer to inode matching "fhandle," or NULL if a matching inode
585 * cannot be found.
586 */
587struct inode *nfs_delegation_find_inode(struct nfs_client *clp,
588 const struct nfs_fh *fhandle)
589{
590 struct nfs_server *server;
591 struct inode *res = NULL;
592
593 rcu_read_lock();
594 list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
595 res = nfs_delegation_find_inode_server(server, fhandle);
596 if (res != NULL)
597 break;
598 }
503 rcu_read_unlock(); 599 rcu_read_unlock();
504 return res; 600 return res;
505} 601}
506 602
507/* 603static void nfs_delegation_mark_reclaim_server(struct nfs_server *server)
508 * Mark all delegations as needing to be reclaimed 604{
605 struct nfs_delegation *delegation;
606
607 list_for_each_entry_rcu(delegation, &server->delegations, super_list)
608 set_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags);
609}
610
611/**
612 * nfs_delegation_mark_reclaim - mark all delegations as needing to be reclaimed
613 * @clp: nfs_client to process
614 *
509 */ 615 */
510void nfs_delegation_mark_reclaim(struct nfs_client *clp) 616void nfs_delegation_mark_reclaim(struct nfs_client *clp)
511{ 617{
512 struct nfs_delegation *delegation; 618 struct nfs_server *server;
619
513 rcu_read_lock(); 620 rcu_read_lock();
514 list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) 621 list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
515 set_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags); 622 nfs_delegation_mark_reclaim_server(server);
516 rcu_read_unlock(); 623 rcu_read_unlock();
517} 624}
518 625
519/* 626/**
520 * Reap all unclaimed delegations after reboot recovery is done 627 * nfs_delegation_reap_unclaimed - reap unclaimed delegations after reboot recovery is done
628 * @clp: nfs_client to process
629 *
521 */ 630 */
522void nfs_delegation_reap_unclaimed(struct nfs_client *clp) 631void nfs_delegation_reap_unclaimed(struct nfs_client *clp)
523{ 632{
524 struct nfs_delegation *delegation; 633 struct nfs_delegation *delegation;
634 struct nfs_server *server;
525 struct inode *inode; 635 struct inode *inode;
636
526restart: 637restart:
527 rcu_read_lock(); 638 rcu_read_lock();
528 list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) { 639 list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
529 if (test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags) == 0) 640 list_for_each_entry_rcu(delegation, &server->delegations,
530 continue; 641 super_list) {
531 inode = nfs_delegation_grab_inode(delegation); 642 if (test_bit(NFS_DELEGATION_NEED_RECLAIM,
532 if (inode == NULL) 643 &delegation->flags) == 0)
533 continue; 644 continue;
534 spin_lock(&clp->cl_lock); 645 inode = nfs_delegation_grab_inode(delegation);
535 delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL, clp); 646 if (inode == NULL)
536 spin_unlock(&clp->cl_lock); 647 continue;
537 rcu_read_unlock(); 648 delegation = nfs_detach_delegation(NFS_I(inode),
538 if (delegation != NULL) 649 server);
539 nfs_free_delegation(delegation); 650 rcu_read_unlock();
540 iput(inode); 651
541 goto restart; 652 if (delegation != NULL)
653 nfs_free_delegation(delegation);
654 iput(inode);
655 goto restart;
656 }
542 } 657 }
543 rcu_read_unlock(); 658 rcu_read_unlock();
544} 659}
545 660
661/**
662 * nfs_delegations_present - check for existence of delegations
663 * @clp: client state handle
664 *
665 * Returns one if there are any nfs_delegation structures attached
666 * to this nfs_client.
667 */
668int nfs_delegations_present(struct nfs_client *clp)
669{
670 struct nfs_server *server;
671 int ret = 0;
672
673 rcu_read_lock();
674 list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
675 if (!list_empty(&server->delegations)) {
676 ret = 1;
677 break;
678 }
679 rcu_read_unlock();
680 return ret;
681}
682
683/**
684 * nfs4_copy_delegation_stateid - Copy inode's state ID information
685 * @dst: stateid data structure to fill in
686 * @inode: inode to check
687 *
688 * Returns one and fills in "dst->data" * if inode had a delegation,
689 * otherwise zero is returned.
690 */
546int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode) 691int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode)
547{ 692{
548 struct nfs_inode *nfsi = NFS_I(inode); 693 struct nfs_inode *nfsi = NFS_I(inode);