diff options
-rw-r--r-- | fs/nfsd/nfs4recover.c | 136 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 63 | ||||
-rw-r--r-- | fs/nfsd/state.h | 15 |
3 files changed, 156 insertions, 58 deletions
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index 6523809839c3..e616f88b7f19 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c | |||
@@ -43,9 +43,20 @@ | |||
43 | 43 | ||
44 | #define NFSDDBG_FACILITY NFSDDBG_PROC | 44 | #define NFSDDBG_FACILITY NFSDDBG_PROC |
45 | 45 | ||
46 | /* Declarations */ | ||
47 | struct nfsd4_client_tracking_ops { | ||
48 | int (*init)(struct net *); | ||
49 | void (*exit)(struct net *); | ||
50 | void (*create)(struct nfs4_client *); | ||
51 | void (*remove)(struct nfs4_client *); | ||
52 | int (*check)(struct nfs4_client *); | ||
53 | void (*grace_done)(struct net *, time_t); | ||
54 | }; | ||
55 | |||
46 | /* Globals */ | 56 | /* Globals */ |
47 | static struct file *rec_file; | 57 | static struct file *rec_file; |
48 | static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery"; | 58 | static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery"; |
59 | static struct nfsd4_client_tracking_ops *client_tracking_ops; | ||
49 | 60 | ||
50 | static int | 61 | static int |
51 | nfs4_save_creds(const struct cred **original_creds) | 62 | nfs4_save_creds(const struct cred **original_creds) |
@@ -117,7 +128,8 @@ out_no_tfm: | |||
117 | return status; | 128 | return status; |
118 | } | 129 | } |
119 | 130 | ||
120 | void nfsd4_create_clid_dir(struct nfs4_client *clp) | 131 | static void |
132 | nfsd4_create_clid_dir(struct nfs4_client *clp) | ||
121 | { | 133 | { |
122 | const struct cred *original_cred; | 134 | const struct cred *original_cred; |
123 | char *dname = clp->cl_recdir; | 135 | char *dname = clp->cl_recdir; |
@@ -264,7 +276,7 @@ out_unlock: | |||
264 | return status; | 276 | return status; |
265 | } | 277 | } |
266 | 278 | ||
267 | void | 279 | static void |
268 | nfsd4_remove_clid_dir(struct nfs4_client *clp) | 280 | nfsd4_remove_clid_dir(struct nfs4_client *clp) |
269 | { | 281 | { |
270 | const struct cred *original_cred; | 282 | const struct cred *original_cred; |
@@ -291,7 +303,6 @@ out: | |||
291 | if (status) | 303 | if (status) |
292 | printk("NFSD: Failed to remove expired client state directory" | 304 | printk("NFSD: Failed to remove expired client state directory" |
293 | " %.*s\n", HEXDIR_LEN, clp->cl_recdir); | 305 | " %.*s\n", HEXDIR_LEN, clp->cl_recdir); |
294 | return; | ||
295 | } | 306 | } |
296 | 307 | ||
297 | static int | 308 | static int |
@@ -310,8 +321,9 @@ purge_old(struct dentry *parent, struct dentry *child) | |||
310 | return 0; | 321 | return 0; |
311 | } | 322 | } |
312 | 323 | ||
313 | void | 324 | static void |
314 | nfsd4_recdir_purge_old(void) { | 325 | nfsd4_recdir_purge_old(struct net *net, time_t boot_time) |
326 | { | ||
315 | int status; | 327 | int status; |
316 | 328 | ||
317 | if (!rec_file) | 329 | if (!rec_file) |
@@ -342,7 +354,7 @@ load_recdir(struct dentry *parent, struct dentry *child) | |||
342 | return 0; | 354 | return 0; |
343 | } | 355 | } |
344 | 356 | ||
345 | int | 357 | static int |
346 | nfsd4_recdir_load(void) { | 358 | nfsd4_recdir_load(void) { |
347 | int status; | 359 | int status; |
348 | 360 | ||
@@ -360,8 +372,8 @@ nfsd4_recdir_load(void) { | |||
360 | * Hold reference to the recovery directory. | 372 | * Hold reference to the recovery directory. |
361 | */ | 373 | */ |
362 | 374 | ||
363 | void | 375 | static int |
364 | nfsd4_init_recdir() | 376 | nfsd4_init_recdir(void) |
365 | { | 377 | { |
366 | const struct cred *original_cred; | 378 | const struct cred *original_cred; |
367 | int status; | 379 | int status; |
@@ -376,20 +388,37 @@ nfsd4_init_recdir() | |||
376 | printk("NFSD: Unable to change credentials to find recovery" | 388 | printk("NFSD: Unable to change credentials to find recovery" |
377 | " directory: error %d\n", | 389 | " directory: error %d\n", |
378 | status); | 390 | status); |
379 | return; | 391 | return status; |
380 | } | 392 | } |
381 | 393 | ||
382 | rec_file = filp_open(user_recovery_dirname, O_RDONLY | O_DIRECTORY, 0); | 394 | rec_file = filp_open(user_recovery_dirname, O_RDONLY | O_DIRECTORY, 0); |
383 | if (IS_ERR(rec_file)) { | 395 | if (IS_ERR(rec_file)) { |
384 | printk("NFSD: unable to find recovery directory %s\n", | 396 | printk("NFSD: unable to find recovery directory %s\n", |
385 | user_recovery_dirname); | 397 | user_recovery_dirname); |
398 | status = PTR_ERR(rec_file); | ||
386 | rec_file = NULL; | 399 | rec_file = NULL; |
387 | } | 400 | } |
388 | 401 | ||
389 | nfs4_reset_creds(original_cred); | 402 | nfs4_reset_creds(original_cred); |
403 | return status; | ||
390 | } | 404 | } |
391 | 405 | ||
392 | void | 406 | static int |
407 | nfsd4_load_reboot_recovery_data(struct net *net) | ||
408 | { | ||
409 | int status; | ||
410 | |||
411 | nfs4_lock_state(); | ||
412 | status = nfsd4_init_recdir(); | ||
413 | if (!status) | ||
414 | status = nfsd4_recdir_load(); | ||
415 | nfs4_unlock_state(); | ||
416 | if (status) | ||
417 | printk(KERN_ERR "NFSD: Failure reading reboot recovery data\n"); | ||
418 | return status; | ||
419 | } | ||
420 | |||
421 | static void | ||
393 | nfsd4_shutdown_recdir(void) | 422 | nfsd4_shutdown_recdir(void) |
394 | { | 423 | { |
395 | if (!rec_file) | 424 | if (!rec_file) |
@@ -398,6 +427,13 @@ nfsd4_shutdown_recdir(void) | |||
398 | rec_file = NULL; | 427 | rec_file = NULL; |
399 | } | 428 | } |
400 | 429 | ||
430 | static void | ||
431 | nfsd4_legacy_tracking_exit(struct net *net) | ||
432 | { | ||
433 | nfs4_release_reclaim(); | ||
434 | nfsd4_shutdown_recdir(); | ||
435 | } | ||
436 | |||
401 | /* | 437 | /* |
402 | * Change the NFSv4 recovery directory to recdir. | 438 | * Change the NFSv4 recovery directory to recdir. |
403 | */ | 439 | */ |
@@ -424,3 +460,83 @@ nfs4_recoverydir(void) | |||
424 | { | 460 | { |
425 | return user_recovery_dirname; | 461 | return user_recovery_dirname; |
426 | } | 462 | } |
463 | |||
464 | static int | ||
465 | nfsd4_check_legacy_client(struct nfs4_client *clp) | ||
466 | { | ||
467 | /* did we already find that this client is stable? */ | ||
468 | if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) | ||
469 | return 0; | ||
470 | |||
471 | /* look for it in the reclaim hashtable otherwise */ | ||
472 | if (nfsd4_find_reclaim_client(clp)) { | ||
473 | set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); | ||
474 | return 0; | ||
475 | } | ||
476 | |||
477 | return -ENOENT; | ||
478 | } | ||
479 | |||
480 | static struct nfsd4_client_tracking_ops nfsd4_legacy_tracking_ops = { | ||
481 | .init = nfsd4_load_reboot_recovery_data, | ||
482 | .exit = nfsd4_legacy_tracking_exit, | ||
483 | .create = nfsd4_create_clid_dir, | ||
484 | .remove = nfsd4_remove_clid_dir, | ||
485 | .check = nfsd4_check_legacy_client, | ||
486 | .grace_done = nfsd4_recdir_purge_old, | ||
487 | }; | ||
488 | |||
489 | int | ||
490 | nfsd4_client_tracking_init(struct net *net) | ||
491 | { | ||
492 | int status; | ||
493 | |||
494 | client_tracking_ops = &nfsd4_legacy_tracking_ops; | ||
495 | |||
496 | status = client_tracking_ops->init(net); | ||
497 | if (status) { | ||
498 | printk(KERN_WARNING "NFSD: Unable to initialize client " | ||
499 | "recovery tracking! (%d)\n", status); | ||
500 | client_tracking_ops = NULL; | ||
501 | } | ||
502 | return status; | ||
503 | } | ||
504 | |||
505 | void | ||
506 | nfsd4_client_tracking_exit(struct net *net) | ||
507 | { | ||
508 | if (client_tracking_ops) { | ||
509 | client_tracking_ops->exit(net); | ||
510 | client_tracking_ops = NULL; | ||
511 | } | ||
512 | } | ||
513 | |||
514 | void | ||
515 | nfsd4_client_record_create(struct nfs4_client *clp) | ||
516 | { | ||
517 | if (client_tracking_ops) | ||
518 | client_tracking_ops->create(clp); | ||
519 | } | ||
520 | |||
521 | void | ||
522 | nfsd4_client_record_remove(struct nfs4_client *clp) | ||
523 | { | ||
524 | if (client_tracking_ops) | ||
525 | client_tracking_ops->remove(clp); | ||
526 | } | ||
527 | |||
528 | int | ||
529 | nfsd4_client_record_check(struct nfs4_client *clp) | ||
530 | { | ||
531 | if (client_tracking_ops) | ||
532 | return client_tracking_ops->check(clp); | ||
533 | |||
534 | return -EOPNOTSUPP; | ||
535 | } | ||
536 | |||
537 | void | ||
538 | nfsd4_record_grace_done(struct net *net, time_t boot_time) | ||
539 | { | ||
540 | if (client_tracking_ops) | ||
541 | client_tracking_ops->grace_done(net, boot_time); | ||
542 | } | ||
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 8be612abd0d7..1841f8bf845e 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -2085,7 +2085,7 @@ nfsd4_reclaim_complete(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta | |||
2085 | goto out; | 2085 | goto out; |
2086 | 2086 | ||
2087 | status = nfs_ok; | 2087 | status = nfs_ok; |
2088 | nfsd4_create_clid_dir(cstate->session->se_client); | 2088 | nfsd4_client_record_create(cstate->session->se_client); |
2089 | out: | 2089 | out: |
2090 | nfs4_unlock_state(); | 2090 | nfs4_unlock_state(); |
2091 | return status; | 2091 | return status; |
@@ -2280,7 +2280,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, | |||
2280 | conf = find_confirmed_client_by_str(unconf->cl_recdir, | 2280 | conf = find_confirmed_client_by_str(unconf->cl_recdir, |
2281 | hash); | 2281 | hash); |
2282 | if (conf) { | 2282 | if (conf) { |
2283 | nfsd4_remove_clid_dir(conf); | 2283 | nfsd4_client_record_remove(conf); |
2284 | expire_client(conf); | 2284 | expire_client(conf); |
2285 | } | 2285 | } |
2286 | move_to_confirmed(unconf); | 2286 | move_to_confirmed(unconf); |
@@ -3159,7 +3159,7 @@ static void | |||
3159 | nfsd4_end_grace(void) | 3159 | nfsd4_end_grace(void) |
3160 | { | 3160 | { |
3161 | dprintk("NFSD: end of grace period\n"); | 3161 | dprintk("NFSD: end of grace period\n"); |
3162 | nfsd4_recdir_purge_old(); | 3162 | nfsd4_record_grace_done(&init_net, boot_time); |
3163 | locks_end_grace(&nfsd4_manager); | 3163 | locks_end_grace(&nfsd4_manager); |
3164 | /* | 3164 | /* |
3165 | * Now that every NFSv4 client has had the chance to recover and | 3165 | * Now that every NFSv4 client has had the chance to recover and |
@@ -3208,7 +3208,7 @@ nfs4_laundromat(void) | |||
3208 | clp = list_entry(pos, struct nfs4_client, cl_lru); | 3208 | clp = list_entry(pos, struct nfs4_client, cl_lru); |
3209 | dprintk("NFSD: purging unused client (clientid %08x)\n", | 3209 | dprintk("NFSD: purging unused client (clientid %08x)\n", |
3210 | clp->cl_clientid.cl_id); | 3210 | clp->cl_clientid.cl_id); |
3211 | nfsd4_remove_clid_dir(clp); | 3211 | nfsd4_client_record_remove(clp); |
3212 | expire_client(clp); | 3212 | expire_client(clp); |
3213 | } | 3213 | } |
3214 | spin_lock(&recall_lock); | 3214 | spin_lock(&recall_lock); |
@@ -3639,7 +3639,7 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
3639 | dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n", | 3639 | dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n", |
3640 | __func__, oc->oc_seqid, STATEID_VAL(&stp->st_stid.sc_stateid)); | 3640 | __func__, oc->oc_seqid, STATEID_VAL(&stp->st_stid.sc_stateid)); |
3641 | 3641 | ||
3642 | nfsd4_create_clid_dir(oo->oo_owner.so_client); | 3642 | nfsd4_client_record_create(oo->oo_owner.so_client); |
3643 | status = nfs_ok; | 3643 | status = nfs_ok; |
3644 | out: | 3644 | out: |
3645 | if (!cstate->replay_owner) | 3645 | if (!cstate->replay_owner) |
@@ -4481,7 +4481,7 @@ nfs4_client_to_reclaim(const char *name) | |||
4481 | return 1; | 4481 | return 1; |
4482 | } | 4482 | } |
4483 | 4483 | ||
4484 | static void | 4484 | void |
4485 | nfs4_release_reclaim(void) | 4485 | nfs4_release_reclaim(void) |
4486 | { | 4486 | { |
4487 | struct nfs4_client_reclaim *crp = NULL; | 4487 | struct nfs4_client_reclaim *crp = NULL; |
@@ -4501,7 +4501,7 @@ nfs4_release_reclaim(void) | |||
4501 | 4501 | ||
4502 | /* | 4502 | /* |
4503 | * called from OPEN, CLAIM_PREVIOUS with a new clientid. */ | 4503 | * called from OPEN, CLAIM_PREVIOUS with a new clientid. */ |
4504 | static struct nfs4_client_reclaim * | 4504 | struct nfs4_client_reclaim * |
4505 | nfsd4_find_reclaim_client(struct nfs4_client *clp) | 4505 | nfsd4_find_reclaim_client(struct nfs4_client *clp) |
4506 | { | 4506 | { |
4507 | unsigned int strhashval; | 4507 | unsigned int strhashval; |
@@ -4521,22 +4521,6 @@ nfsd4_find_reclaim_client(struct nfs4_client *clp) | |||
4521 | return NULL; | 4521 | return NULL; |
4522 | } | 4522 | } |
4523 | 4523 | ||
4524 | static int | ||
4525 | nfsd4_client_record_check(struct nfs4_client *clp) | ||
4526 | { | ||
4527 | /* did we already find that this client is stable? */ | ||
4528 | if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) | ||
4529 | return 0; | ||
4530 | |||
4531 | /* look for it in the reclaim hashtable otherwise */ | ||
4532 | if (nfsd4_find_reclaim_client(clp)) { | ||
4533 | set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); | ||
4534 | return 0; | ||
4535 | } | ||
4536 | |||
4537 | return -ENOENT; | ||
4538 | } | ||
4539 | |||
4540 | /* | 4524 | /* |
4541 | * Called from OPEN. Look for clientid in reclaim list. | 4525 | * Called from OPEN. Look for clientid in reclaim list. |
4542 | */ | 4526 | */ |
@@ -4562,7 +4546,7 @@ void nfsd_forget_clients(u64 num) | |||
4562 | 4546 | ||
4563 | nfs4_lock_state(); | 4547 | nfs4_lock_state(); |
4564 | list_for_each_entry_safe(clp, next, &client_lru, cl_lru) { | 4548 | list_for_each_entry_safe(clp, next, &client_lru, cl_lru) { |
4565 | nfsd4_remove_clid_dir(clp); | 4549 | nfsd4_client_record_remove(clp); |
4566 | expire_client(clp); | 4550 | expire_client(clp); |
4567 | if (++count == num) | 4551 | if (++count == num) |
4568 | break; | 4552 | break; |
@@ -4697,19 +4681,6 @@ nfs4_state_init(void) | |||
4697 | reclaim_str_hashtbl_size = 0; | 4681 | reclaim_str_hashtbl_size = 0; |
4698 | } | 4682 | } |
4699 | 4683 | ||
4700 | static void | ||
4701 | nfsd4_load_reboot_recovery_data(void) | ||
4702 | { | ||
4703 | int status; | ||
4704 | |||
4705 | nfs4_lock_state(); | ||
4706 | nfsd4_init_recdir(); | ||
4707 | status = nfsd4_recdir_load(); | ||
4708 | nfs4_unlock_state(); | ||
4709 | if (status) | ||
4710 | printk("NFSD: Failure reading reboot recovery data\n"); | ||
4711 | } | ||
4712 | |||
4713 | /* | 4684 | /* |
4714 | * Since the lifetime of a delegation isn't limited to that of an open, a | 4685 | * Since the lifetime of a delegation isn't limited to that of an open, a |
4715 | * client may quite reasonably hang on to a delegation as long as it has | 4686 | * client may quite reasonably hang on to a delegation as long as it has |
@@ -4738,7 +4709,15 @@ nfs4_state_start(void) | |||
4738 | { | 4709 | { |
4739 | int ret; | 4710 | int ret; |
4740 | 4711 | ||
4741 | nfsd4_load_reboot_recovery_data(); | 4712 | /* |
4713 | * FIXME: For now, we hang most of the pernet global stuff off of | ||
4714 | * init_net until nfsd is fully containerized. Eventually, we'll | ||
4715 | * need to pass a net pointer into this function, take a reference | ||
4716 | * to that instead and then do most of the rest of this on a per-net | ||
4717 | * basis. | ||
4718 | */ | ||
4719 | get_net(&init_net); | ||
4720 | nfsd4_client_tracking_init(&init_net); | ||
4742 | boot_time = get_seconds(); | 4721 | boot_time = get_seconds(); |
4743 | locks_start_grace(&nfsd4_manager); | 4722 | locks_start_grace(&nfsd4_manager); |
4744 | printk(KERN_INFO "NFSD: starting %ld-second grace period\n", | 4723 | printk(KERN_INFO "NFSD: starting %ld-second grace period\n", |
@@ -4762,8 +4741,8 @@ nfs4_state_start(void) | |||
4762 | out_free_laundry: | 4741 | out_free_laundry: |
4763 | destroy_workqueue(laundry_wq); | 4742 | destroy_workqueue(laundry_wq); |
4764 | out_recovery: | 4743 | out_recovery: |
4765 | nfs4_release_reclaim(); | 4744 | nfsd4_client_tracking_exit(&init_net); |
4766 | nfsd4_shutdown_recdir(); | 4745 | put_net(&init_net); |
4767 | return ret; | 4746 | return ret; |
4768 | } | 4747 | } |
4769 | 4748 | ||
@@ -4797,7 +4776,8 @@ __nfs4_state_shutdown(void) | |||
4797 | unhash_delegation(dp); | 4776 | unhash_delegation(dp); |
4798 | } | 4777 | } |
4799 | 4778 | ||
4800 | nfsd4_shutdown_recdir(); | 4779 | nfsd4_client_tracking_exit(&init_net); |
4780 | put_net(&init_net); | ||
4801 | } | 4781 | } |
4802 | 4782 | ||
4803 | void | 4783 | void |
@@ -4807,7 +4787,6 @@ nfs4_state_shutdown(void) | |||
4807 | destroy_workqueue(laundry_wq); | 4787 | destroy_workqueue(laundry_wq); |
4808 | locks_end_grace(&nfsd4_manager); | 4788 | locks_end_grace(&nfsd4_manager); |
4809 | nfs4_lock_state(); | 4789 | nfs4_lock_state(); |
4810 | nfs4_release_reclaim(); | ||
4811 | __nfs4_state_shutdown(); | 4790 | __nfs4_state_shutdown(); |
4812 | nfs4_unlock_state(); | 4791 | nfs4_unlock_state(); |
4813 | nfsd4_destroy_callback_queue(); | 4792 | nfsd4_destroy_callback_queue(); |
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 115215723f76..89ab137d379a 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h | |||
@@ -457,6 +457,8 @@ extern __be32 nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate, | |||
457 | extern void nfs4_lock_state(void); | 457 | extern void nfs4_lock_state(void); |
458 | extern void nfs4_unlock_state(void); | 458 | extern void nfs4_unlock_state(void); |
459 | extern int nfs4_in_grace(void); | 459 | extern int nfs4_in_grace(void); |
460 | extern void nfs4_release_reclaim(void); | ||
461 | extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(struct nfs4_client *crp); | ||
460 | extern __be32 nfs4_check_open_reclaim(clientid_t *clid); | 462 | extern __be32 nfs4_check_open_reclaim(clientid_t *clid); |
461 | extern void nfs4_free_openowner(struct nfs4_openowner *); | 463 | extern void nfs4_free_openowner(struct nfs4_openowner *); |
462 | extern void nfs4_free_lockowner(struct nfs4_lockowner *); | 464 | extern void nfs4_free_lockowner(struct nfs4_lockowner *); |
@@ -471,16 +473,17 @@ extern void nfsd4_destroy_callback_queue(void); | |||
471 | extern void nfsd4_shutdown_callback(struct nfs4_client *); | 473 | extern void nfsd4_shutdown_callback(struct nfs4_client *); |
472 | extern void nfs4_put_delegation(struct nfs4_delegation *dp); | 474 | extern void nfs4_put_delegation(struct nfs4_delegation *dp); |
473 | extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname); | 475 | extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname); |
474 | extern void nfsd4_init_recdir(void); | ||
475 | extern int nfsd4_recdir_load(void); | ||
476 | extern void nfsd4_shutdown_recdir(void); | ||
477 | extern int nfs4_client_to_reclaim(const char *name); | 476 | extern int nfs4_client_to_reclaim(const char *name); |
478 | extern int nfs4_has_reclaimed_state(const char *name, bool use_exchange_id); | 477 | extern int nfs4_has_reclaimed_state(const char *name, bool use_exchange_id); |
479 | extern void nfsd4_recdir_purge_old(void); | ||
480 | extern void nfsd4_create_clid_dir(struct nfs4_client *clp); | ||
481 | extern void nfsd4_remove_clid_dir(struct nfs4_client *clp); | ||
482 | extern void release_session_client(struct nfsd4_session *); | 478 | extern void release_session_client(struct nfsd4_session *); |
483 | extern __be32 nfs4_validate_stateid(struct nfs4_client *, stateid_t *); | 479 | extern __be32 nfs4_validate_stateid(struct nfs4_client *, stateid_t *); |
484 | extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *); | 480 | extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *); |
485 | 481 | ||
482 | /* nfs4recover operations */ | ||
483 | extern int nfsd4_client_tracking_init(struct net *net); | ||
484 | extern void nfsd4_client_tracking_exit(struct net *net); | ||
485 | extern void nfsd4_client_record_create(struct nfs4_client *clp); | ||
486 | extern void nfsd4_client_record_remove(struct nfs4_client *clp); | ||
487 | extern int nfsd4_client_record_check(struct nfs4_client *clp); | ||
488 | extern void nfsd4_record_grace_done(struct net *net, time_t boot_time); | ||
486 | #endif /* NFSD4_STATE_H */ | 489 | #endif /* NFSD4_STATE_H */ |