aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4state.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r--fs/nfsd/nfs4state.c163
1 files changed, 66 insertions, 97 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 6a8fedaa4f55..f05a3276ba6b 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -45,8 +45,8 @@
45#define NFSDDBG_FACILITY NFSDDBG_PROC 45#define NFSDDBG_FACILITY NFSDDBG_PROC
46 46
47/* Globals */ 47/* Globals */
48static time_t lease_time = 90; /* default lease time */ 48time_t nfsd4_lease = 90; /* default lease time */
49static time_t user_lease_time = 90; 49time_t nfsd4_grace = 90;
50static time_t boot_time; 50static time_t boot_time;
51static u32 current_ownerid = 1; 51static u32 current_ownerid = 1;
52static u32 current_fileid = 1; 52static u32 current_fileid = 1;
@@ -199,6 +199,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
199 atomic_set(&dp->dl_count, 1); 199 atomic_set(&dp->dl_count, 1);
200 list_add(&dp->dl_perfile, &fp->fi_delegations); 200 list_add(&dp->dl_perfile, &fp->fi_delegations);
201 list_add(&dp->dl_perclnt, &clp->cl_delegations); 201 list_add(&dp->dl_perclnt, &clp->cl_delegations);
202 INIT_WORK(&dp->dl_recall.cb_work, nfsd4_do_callback_rpc);
202 return dp; 203 return dp;
203} 204}
204 205
@@ -680,27 +681,9 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name)
680 return clp; 681 return clp;
681} 682}
682 683
683static void
684shutdown_callback_client(struct nfs4_client *clp)
685{
686 struct rpc_clnt *clnt = clp->cl_cb_conn.cb_client;
687
688 if (clnt) {
689 /*
690 * Callback threads take a reference on the client, so there
691 * should be no outstanding callbacks at this point.
692 */
693 clp->cl_cb_conn.cb_client = NULL;
694 rpc_shutdown_client(clnt);
695 }
696}
697
698static inline void 684static inline void
699free_client(struct nfs4_client *clp) 685free_client(struct nfs4_client *clp)
700{ 686{
701 shutdown_callback_client(clp);
702 if (clp->cl_cb_xprt)
703 svc_xprt_put(clp->cl_cb_xprt);
704 if (clp->cl_cred.cr_group_info) 687 if (clp->cl_cred.cr_group_info)
705 put_group_info(clp->cl_cred.cr_group_info); 688 put_group_info(clp->cl_cred.cr_group_info);
706 kfree(clp->cl_principal); 689 kfree(clp->cl_principal);
@@ -708,13 +691,6 @@ free_client(struct nfs4_client *clp)
708 kfree(clp); 691 kfree(clp);
709} 692}
710 693
711void
712put_nfs4_client(struct nfs4_client *clp)
713{
714 if (atomic_dec_and_test(&clp->cl_count))
715 free_client(clp);
716}
717
718static void 694static void
719expire_client(struct nfs4_client *clp) 695expire_client(struct nfs4_client *clp)
720{ 696{
@@ -722,9 +698,6 @@ expire_client(struct nfs4_client *clp)
722 struct nfs4_delegation *dp; 698 struct nfs4_delegation *dp;
723 struct list_head reaplist; 699 struct list_head reaplist;
724 700
725 dprintk("NFSD: expire_client cl_count %d\n",
726 atomic_read(&clp->cl_count));
727
728 INIT_LIST_HEAD(&reaplist); 701 INIT_LIST_HEAD(&reaplist);
729 spin_lock(&recall_lock); 702 spin_lock(&recall_lock);
730 while (!list_empty(&clp->cl_delegations)) { 703 while (!list_empty(&clp->cl_delegations)) {
@@ -753,7 +726,10 @@ expire_client(struct nfs4_client *clp)
753 se_perclnt); 726 se_perclnt);
754 release_session(ses); 727 release_session(ses);
755 } 728 }
756 put_nfs4_client(clp); 729 nfsd4_set_callback_client(clp, NULL);
730 if (clp->cl_cb_conn.cb_xprt)
731 svc_xprt_put(clp->cl_cb_conn.cb_xprt);
732 free_client(clp);
757} 733}
758 734
759static void copy_verf(struct nfs4_client *target, nfs4_verifier *source) 735static void copy_verf(struct nfs4_client *target, nfs4_verifier *source)
@@ -839,8 +815,7 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir,
839 } 815 }
840 816
841 memcpy(clp->cl_recdir, recdir, HEXDIR_LEN); 817 memcpy(clp->cl_recdir, recdir, HEXDIR_LEN);
842 atomic_set(&clp->cl_count, 1); 818 atomic_set(&clp->cl_cb_set, 0);
843 atomic_set(&clp->cl_cb_conn.cb_set, 0);
844 INIT_LIST_HEAD(&clp->cl_idhash); 819 INIT_LIST_HEAD(&clp->cl_idhash);
845 INIT_LIST_HEAD(&clp->cl_strhash); 820 INIT_LIST_HEAD(&clp->cl_strhash);
846 INIT_LIST_HEAD(&clp->cl_openowners); 821 INIT_LIST_HEAD(&clp->cl_openowners);
@@ -1327,15 +1302,9 @@ nfsd4_create_session(struct svc_rqst *rqstp,
1327 cs_slot->sl_seqid++; /* from 0 to 1 */ 1302 cs_slot->sl_seqid++; /* from 0 to 1 */
1328 move_to_confirmed(unconf); 1303 move_to_confirmed(unconf);
1329 1304
1330 /*
1331 * We do not support RDMA or persistent sessions
1332 */
1333 cr_ses->flags &= ~SESSION4_PERSIST;
1334 cr_ses->flags &= ~SESSION4_RDMA;
1335
1336 if (cr_ses->flags & SESSION4_BACK_CHAN) { 1305 if (cr_ses->flags & SESSION4_BACK_CHAN) {
1337 unconf->cl_cb_xprt = rqstp->rq_xprt; 1306 unconf->cl_cb_conn.cb_xprt = rqstp->rq_xprt;
1338 svc_xprt_get(unconf->cl_cb_xprt); 1307 svc_xprt_get(rqstp->rq_xprt);
1339 rpc_copy_addr( 1308 rpc_copy_addr(
1340 (struct sockaddr *)&unconf->cl_cb_conn.cb_addr, 1309 (struct sockaddr *)&unconf->cl_cb_conn.cb_addr,
1341 sa); 1310 sa);
@@ -1344,7 +1313,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
1344 cstate->minorversion; 1313 cstate->minorversion;
1345 unconf->cl_cb_conn.cb_prog = cr_ses->callback_prog; 1314 unconf->cl_cb_conn.cb_prog = cr_ses->callback_prog;
1346 unconf->cl_cb_seq_nr = 1; 1315 unconf->cl_cb_seq_nr = 1;
1347 nfsd4_probe_callback(unconf); 1316 nfsd4_probe_callback(unconf, &unconf->cl_cb_conn);
1348 } 1317 }
1349 conf = unconf; 1318 conf = unconf;
1350 } else { 1319 } else {
@@ -1352,6 +1321,12 @@ nfsd4_create_session(struct svc_rqst *rqstp,
1352 goto out; 1321 goto out;
1353 } 1322 }
1354 1323
1324 /*
1325 * We do not support RDMA or persistent sessions
1326 */
1327 cr_ses->flags &= ~SESSION4_PERSIST;
1328 cr_ses->flags &= ~SESSION4_RDMA;
1329
1355 status = alloc_init_session(rqstp, conf, cr_ses); 1330 status = alloc_init_session(rqstp, conf, cr_ses);
1356 if (status) 1331 if (status)
1357 goto out; 1332 goto out;
@@ -1369,6 +1344,14 @@ out:
1369 return status; 1344 return status;
1370} 1345}
1371 1346
1347static bool nfsd4_last_compound_op(struct svc_rqst *rqstp)
1348{
1349 struct nfsd4_compoundres *resp = rqstp->rq_resp;
1350 struct nfsd4_compoundargs *argp = rqstp->rq_argp;
1351
1352 return argp->opcnt == resp->opcnt;
1353}
1354
1372__be32 1355__be32
1373nfsd4_destroy_session(struct svc_rqst *r, 1356nfsd4_destroy_session(struct svc_rqst *r,
1374 struct nfsd4_compound_state *cstate, 1357 struct nfsd4_compound_state *cstate,
@@ -1384,6 +1367,11 @@ nfsd4_destroy_session(struct svc_rqst *r,
1384 * - Do we need to clear any callback info from previous session? 1367 * - Do we need to clear any callback info from previous session?
1385 */ 1368 */
1386 1369
1370 if (!memcmp(&sessionid->sessionid, &cstate->session->se_sessionid,
1371 sizeof(struct nfs4_sessionid))) {
1372 if (!nfsd4_last_compound_op(r))
1373 return nfserr_not_only_op;
1374 }
1387 dump_sessionid(__func__, &sessionid->sessionid); 1375 dump_sessionid(__func__, &sessionid->sessionid);
1388 spin_lock(&sessionid_lock); 1376 spin_lock(&sessionid_lock);
1389 ses = find_in_sessionid_hashtbl(&sessionid->sessionid); 1377 ses = find_in_sessionid_hashtbl(&sessionid->sessionid);
@@ -1396,7 +1384,7 @@ nfsd4_destroy_session(struct svc_rqst *r,
1396 spin_unlock(&sessionid_lock); 1384 spin_unlock(&sessionid_lock);
1397 1385
1398 /* wait for callbacks */ 1386 /* wait for callbacks */
1399 shutdown_callback_client(ses->se_client); 1387 nfsd4_set_callback_client(ses->se_client, NULL);
1400 nfsd4_put_session(ses); 1388 nfsd4_put_session(ses);
1401 status = nfs_ok; 1389 status = nfs_ok;
1402out: 1390out:
@@ -1456,11 +1444,10 @@ nfsd4_sequence(struct svc_rqst *rqstp,
1456 cstate->slot = slot; 1444 cstate->slot = slot;
1457 cstate->session = session; 1445 cstate->session = session;
1458 1446
1459 /* Hold a session reference until done processing the compound:
1460 * nfsd4_put_session called only if the cstate slot is set.
1461 */
1462 nfsd4_get_session(session);
1463out: 1447out:
1448 /* Hold a session reference until done processing the compound. */
1449 if (cstate->session)
1450 nfsd4_get_session(cstate->session);
1464 spin_unlock(&sessionid_lock); 1451 spin_unlock(&sessionid_lock);
1465 /* Renew the clientid on success and on replay */ 1452 /* Renew the clientid on success and on replay */
1466 if (cstate->session) { 1453 if (cstate->session) {
@@ -1631,9 +1618,8 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
1631 if (!same_creds(&conf->cl_cred, &unconf->cl_cred)) 1618 if (!same_creds(&conf->cl_cred, &unconf->cl_cred))
1632 status = nfserr_clid_inuse; 1619 status = nfserr_clid_inuse;
1633 else { 1620 else {
1634 /* XXX: We just turn off callbacks until we can handle 1621 atomic_set(&conf->cl_cb_set, 0);
1635 * change request correctly. */ 1622 nfsd4_probe_callback(conf, &unconf->cl_cb_conn);
1636 atomic_set(&conf->cl_cb_conn.cb_set, 0);
1637 expire_client(unconf); 1623 expire_client(unconf);
1638 status = nfs_ok; 1624 status = nfs_ok;
1639 1625
@@ -1667,7 +1653,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
1667 } 1653 }
1668 move_to_confirmed(unconf); 1654 move_to_confirmed(unconf);
1669 conf = unconf; 1655 conf = unconf;
1670 nfsd4_probe_callback(conf); 1656 nfsd4_probe_callback(conf, &conf->cl_cb_conn);
1671 status = nfs_ok; 1657 status = nfs_ok;
1672 } 1658 }
1673 } else if ((!conf || (conf && !same_verf(&conf->cl_confirm, &confirm))) 1659 } else if ((!conf || (conf && !same_verf(&conf->cl_confirm, &confirm)))
@@ -2028,7 +2014,6 @@ void nfsd_break_deleg_cb(struct file_lock *fl)
2028 * lock) we know the server hasn't removed the lease yet, we know 2014 * lock) we know the server hasn't removed the lease yet, we know
2029 * it's safe to take a reference: */ 2015 * it's safe to take a reference: */
2030 atomic_inc(&dp->dl_count); 2016 atomic_inc(&dp->dl_count);
2031 atomic_inc(&dp->dl_client->cl_count);
2032 2017
2033 spin_lock(&recall_lock); 2018 spin_lock(&recall_lock);
2034 list_add_tail(&dp->dl_recall_lru, &del_recall_lru); 2019 list_add_tail(&dp->dl_recall_lru, &del_recall_lru);
@@ -2347,7 +2332,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
2347{ 2332{
2348 struct nfs4_delegation *dp; 2333 struct nfs4_delegation *dp;
2349 struct nfs4_stateowner *sop = stp->st_stateowner; 2334 struct nfs4_stateowner *sop = stp->st_stateowner;
2350 struct nfs4_cb_conn *cb = &sop->so_client->cl_cb_conn; 2335 int cb_up = atomic_read(&sop->so_client->cl_cb_set);
2351 struct file_lock fl, *flp = &fl; 2336 struct file_lock fl, *flp = &fl;
2352 int status, flag = 0; 2337 int status, flag = 0;
2353 2338
@@ -2355,7 +2340,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
2355 open->op_recall = 0; 2340 open->op_recall = 0;
2356 switch (open->op_claim_type) { 2341 switch (open->op_claim_type) {
2357 case NFS4_OPEN_CLAIM_PREVIOUS: 2342 case NFS4_OPEN_CLAIM_PREVIOUS:
2358 if (!atomic_read(&cb->cb_set)) 2343 if (!cb_up)
2359 open->op_recall = 1; 2344 open->op_recall = 1;
2360 flag = open->op_delegate_type; 2345 flag = open->op_delegate_type;
2361 if (flag == NFS4_OPEN_DELEGATE_NONE) 2346 if (flag == NFS4_OPEN_DELEGATE_NONE)
@@ -2366,7 +2351,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
2366 * had the chance to reclaim theirs.... */ 2351 * had the chance to reclaim theirs.... */
2367 if (locks_in_grace()) 2352 if (locks_in_grace())
2368 goto out; 2353 goto out;
2369 if (!atomic_read(&cb->cb_set) || !sop->so_confirmed) 2354 if (!cb_up || !sop->so_confirmed)
2370 goto out; 2355 goto out;
2371 if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) 2356 if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
2372 flag = NFS4_OPEN_DELEGATE_WRITE; 2357 flag = NFS4_OPEN_DELEGATE_WRITE;
@@ -2537,7 +2522,7 @@ nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2537 renew_client(clp); 2522 renew_client(clp);
2538 status = nfserr_cb_path_down; 2523 status = nfserr_cb_path_down;
2539 if (!list_empty(&clp->cl_delegations) 2524 if (!list_empty(&clp->cl_delegations)
2540 && !atomic_read(&clp->cl_cb_conn.cb_set)) 2525 && !atomic_read(&clp->cl_cb_set))
2541 goto out; 2526 goto out;
2542 status = nfs_ok; 2527 status = nfs_ok;
2543out: 2528out:
@@ -2554,6 +2539,12 @@ nfsd4_end_grace(void)
2554 dprintk("NFSD: end of grace period\n"); 2539 dprintk("NFSD: end of grace period\n");
2555 nfsd4_recdir_purge_old(); 2540 nfsd4_recdir_purge_old();
2556 locks_end_grace(&nfsd4_manager); 2541 locks_end_grace(&nfsd4_manager);
2542 /*
2543 * Now that every NFSv4 client has had the chance to recover and
2544 * to see the (possibly new, possibly shorter) lease time, we
2545 * can safely set the next grace time to the current lease time:
2546 */
2547 nfsd4_grace = nfsd4_lease;
2557} 2548}
2558 2549
2559static time_t 2550static time_t
@@ -2563,9 +2554,9 @@ nfs4_laundromat(void)
2563 struct nfs4_stateowner *sop; 2554 struct nfs4_stateowner *sop;
2564 struct nfs4_delegation *dp; 2555 struct nfs4_delegation *dp;
2565 struct list_head *pos, *next, reaplist; 2556 struct list_head *pos, *next, reaplist;
2566 time_t cutoff = get_seconds() - NFSD_LEASE_TIME; 2557 time_t cutoff = get_seconds() - nfsd4_lease;
2567 time_t t, clientid_val = NFSD_LEASE_TIME; 2558 time_t t, clientid_val = nfsd4_lease;
2568 time_t u, test_val = NFSD_LEASE_TIME; 2559 time_t u, test_val = nfsd4_lease;
2569 2560
2570 nfs4_lock_state(); 2561 nfs4_lock_state();
2571 2562
@@ -2605,7 +2596,7 @@ nfs4_laundromat(void)
2605 list_del_init(&dp->dl_recall_lru); 2596 list_del_init(&dp->dl_recall_lru);
2606 unhash_delegation(dp); 2597 unhash_delegation(dp);
2607 } 2598 }
2608 test_val = NFSD_LEASE_TIME; 2599 test_val = nfsd4_lease;
2609 list_for_each_safe(pos, next, &close_lru) { 2600 list_for_each_safe(pos, next, &close_lru) {
2610 sop = list_entry(pos, struct nfs4_stateowner, so_close_lru); 2601 sop = list_entry(pos, struct nfs4_stateowner, so_close_lru);
2611 if (time_after((unsigned long)sop->so_time, (unsigned long)cutoff)) { 2602 if (time_after((unsigned long)sop->so_time, (unsigned long)cutoff)) {
@@ -2675,7 +2666,7 @@ EXPIRED_STATEID(stateid_t *stateid)
2675{ 2666{
2676 if (time_before((unsigned long)boot_time, 2667 if (time_before((unsigned long)boot_time,
2677 ((unsigned long)stateid->si_boot)) && 2668 ((unsigned long)stateid->si_boot)) &&
2678 time_before((unsigned long)(stateid->si_boot + lease_time), get_seconds())) { 2669 time_before((unsigned long)(stateid->si_boot + nfsd4_lease), get_seconds())) {
2679 dprintk("NFSD: expired stateid " STATEID_FMT "!\n", 2670 dprintk("NFSD: expired stateid " STATEID_FMT "!\n",
2680 STATEID_VAL(stateid)); 2671 STATEID_VAL(stateid));
2681 return 1; 2672 return 1;
@@ -3976,12 +3967,6 @@ nfsd4_load_reboot_recovery_data(void)
3976 printk("NFSD: Failure reading reboot recovery data\n"); 3967 printk("NFSD: Failure reading reboot recovery data\n");
3977} 3968}
3978 3969
3979unsigned long
3980get_nfs4_grace_period(void)
3981{
3982 return max(user_lease_time, lease_time) * HZ;
3983}
3984
3985/* 3970/*
3986 * Since the lifetime of a delegation isn't limited to that of an open, a 3971 * Since the lifetime of a delegation isn't limited to that of an open, a
3987 * client may quite reasonably hang on to a delegation as long as it has 3972 * client may quite reasonably hang on to a delegation as long as it has
@@ -4008,20 +3993,27 @@ set_max_delegations(void)
4008static int 3993static int
4009__nfs4_state_start(void) 3994__nfs4_state_start(void)
4010{ 3995{
4011 unsigned long grace_time; 3996 int ret;
4012 3997
4013 boot_time = get_seconds(); 3998 boot_time = get_seconds();
4014 grace_time = get_nfs4_grace_period();
4015 lease_time = user_lease_time;
4016 locks_start_grace(&nfsd4_manager); 3999 locks_start_grace(&nfsd4_manager);
4017 printk(KERN_INFO "NFSD: starting %ld-second grace period\n", 4000 printk(KERN_INFO "NFSD: starting %ld-second grace period\n",
4018 grace_time/HZ); 4001 nfsd4_grace);
4002 ret = set_callback_cred();
4003 if (ret)
4004 return -ENOMEM;
4019 laundry_wq = create_singlethread_workqueue("nfsd4"); 4005 laundry_wq = create_singlethread_workqueue("nfsd4");
4020 if (laundry_wq == NULL) 4006 if (laundry_wq == NULL)
4021 return -ENOMEM; 4007 return -ENOMEM;
4022 queue_delayed_work(laundry_wq, &laundromat_work, grace_time); 4008 ret = nfsd4_create_callback_queue();
4009 if (ret)
4010 goto out_free_laundry;
4011 queue_delayed_work(laundry_wq, &laundromat_work, nfsd4_grace * HZ);
4023 set_max_delegations(); 4012 set_max_delegations();
4024 return set_callback_cred(); 4013 return 0;
4014out_free_laundry:
4015 destroy_workqueue(laundry_wq);
4016 return ret;
4025} 4017}
4026 4018
4027int 4019int
@@ -4039,12 +4031,6 @@ nfs4_state_start(void)
4039 return 0; 4031 return 0;
4040} 4032}
4041 4033
4042time_t
4043nfs4_lease_time(void)
4044{
4045 return lease_time;
4046}
4047
4048static void 4034static void
4049__nfs4_state_shutdown(void) 4035__nfs4_state_shutdown(void)
4050{ 4036{
@@ -4089,6 +4075,7 @@ nfs4_state_shutdown(void)
4089 nfs4_lock_state(); 4075 nfs4_lock_state();
4090 nfs4_release_reclaim(); 4076 nfs4_release_reclaim();
4091 __nfs4_state_shutdown(); 4077 __nfs4_state_shutdown();
4078 nfsd4_destroy_callback_queue();
4092 nfs4_unlock_state(); 4079 nfs4_unlock_state();
4093} 4080}
4094 4081
@@ -4128,21 +4115,3 @@ nfs4_recoverydir(void)
4128{ 4115{
4129 return user_recovery_dirname; 4116 return user_recovery_dirname;
4130} 4117}
4131
4132/*
4133 * Called when leasetime is changed.
4134 *
4135 * The only way the protocol gives us to handle on-the-fly lease changes is to
4136 * simulate a reboot. Instead of doing that, we just wait till the next time
4137 * we start to register any changes in lease time. If the administrator
4138 * really wants to change the lease time *now*, they can go ahead and bring
4139 * nfsd down and then back up again after changing the lease time.
4140 *
4141 * user_lease_time is protected by nfsd_mutex since it's only really accessed
4142 * when nfsd is starting
4143 */
4144void
4145nfs4_reset_lease(time_t leasetime)
4146{
4147 user_lease_time = leasetime;
4148}