@@ -84,7 +84,7 @@ static u64 current_sessionid = 1;
8484/* forward declarations */
8585static bool check_for_locks (struct nfs4_file * fp , struct nfs4_lockowner * lowner );
8686static void nfs4_free_ol_stateid (struct nfs4_stid * stid );
87- void nfsd4_end_grace (struct nfsd_net * nn );
87+ static void nfsd4_end_grace (struct nfsd_net * nn );
8888static void _free_cpntf_state_locked (struct nfsd_net * nn , struct nfs4_cpntf_state * cps );
8989static void nfsd4_file_hash_remove (struct nfs4_file * fi );
9090static void deleg_reaper (struct nfsd_net * nn );
@@ -1759,7 +1759,7 @@ static struct nfs4_stid *find_one_sb_stid(struct nfs4_client *clp,
17591759
17601760/**
17611761 * nfsd4_revoke_states - revoke all nfsv4 states associated with given filesystem
1762- * @net: used to identify instance of nfsd (there is one per net namespace)
1762+ * @nn: used to identify instance of nfsd (there is one per net namespace)
17631763 * @sb: super_block used to identify target filesystem
17641764 *
17651765 * All nfs4 states (open, lock, delegation, layout) held by the server instance
@@ -1771,16 +1771,15 @@ static struct nfs4_stid *find_one_sb_stid(struct nfs4_client *clp,
17711771 * The clients which own the states will subsequently being notified that the
17721772 * states have been "admin-revoked".
17731773 */
1774- void nfsd4_revoke_states (struct net * net , struct super_block * sb )
1774+ void nfsd4_revoke_states (struct nfsd_net * nn , struct super_block * sb )
17751775{
1776- struct nfsd_net * nn = net_generic (net , nfsd_net_id );
17771776 unsigned int idhashval ;
17781777 unsigned int sc_types ;
17791778
17801779 sc_types = SC_TYPE_OPEN | SC_TYPE_LOCK | SC_TYPE_DELEG | SC_TYPE_LAYOUT ;
17811780
17821781 spin_lock (& nn -> client_lock );
1783- for (idhashval = 0 ; idhashval < CLIENT_HASH_MASK ; idhashval ++ ) {
1782+ for (idhashval = 0 ; idhashval < CLIENT_HASH_SIZE ; idhashval ++ ) {
17841783 struct list_head * head = & nn -> conf_id_hashtbl [idhashval ];
17851784 struct nfs4_client * clp ;
17861785 retry :
@@ -6570,7 +6569,7 @@ nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
65706569 return nfs_ok ;
65716570}
65726571
6573- void
6572+ static void
65746573nfsd4_end_grace (struct nfsd_net * nn )
65756574{
65766575 /* do nothing if grace period already ended */
@@ -6603,6 +6602,33 @@ nfsd4_end_grace(struct nfsd_net *nn)
66036602 */
66046603}
66056604
6605+ /**
6606+ * nfsd4_force_end_grace - forcibly end the NFSv4 grace period
6607+ * @nn: network namespace for the server instance to be updated
6608+ *
6609+ * Forces bypass of normal grace period completion, then schedules
6610+ * the laundromat to end the grace period immediately. Does not wait
6611+ * for the grace period to fully terminate before returning.
6612+ *
6613+ * Return values:
6614+ * %true: Grace termination schedule
6615+ * %false: No action was taken
6616+ */
6617+ bool nfsd4_force_end_grace (struct nfsd_net * nn )
6618+ {
6619+ if (!nn -> client_tracking_ops )
6620+ return false;
6621+ spin_lock (& nn -> client_lock );
6622+ if (nn -> grace_ended || !nn -> client_tracking_active ) {
6623+ spin_unlock (& nn -> client_lock );
6624+ return false;
6625+ }
6626+ WRITE_ONCE (nn -> grace_end_forced , true);
6627+ mod_delayed_work (laundry_wq , & nn -> laundromat_work , 0 );
6628+ spin_unlock (& nn -> client_lock );
6629+ return true;
6630+ }
6631+
66066632/*
66076633 * If we've waited a lease period but there are still clients trying to
66086634 * reclaim, wait a little longer to give them a chance to finish.
@@ -6612,6 +6638,8 @@ static bool clients_still_reclaiming(struct nfsd_net *nn)
66126638 time64_t double_grace_period_end = nn -> boot_time +
66136639 2 * nn -> nfsd4_lease ;
66146640
6641+ if (READ_ONCE (nn -> grace_end_forced ))
6642+ return false;
66156643 if (nn -> track_reclaim_completes &&
66166644 atomic_read (& nn -> nr_reclaim_complete ) ==
66176645 nn -> reclaim_str_hashtbl_size )
@@ -8932,6 +8960,8 @@ static int nfs4_state_create_net(struct net *net)
89328960 nn -> unconf_name_tree = RB_ROOT ;
89338961 nn -> boot_time = ktime_get_real_seconds ();
89348962 nn -> grace_ended = false;
8963+ nn -> grace_end_forced = false;
8964+ nn -> client_tracking_active = false;
89358965 nn -> nfsd4_manager .block_opens = true;
89368966 INIT_LIST_HEAD (& nn -> nfsd4_manager .list );
89378967 INIT_LIST_HEAD (& nn -> client_lru );
@@ -9012,6 +9042,10 @@ nfs4_state_start_net(struct net *net)
90129042 return ret ;
90139043 locks_start_grace (net , & nn -> nfsd4_manager );
90149044 nfsd4_client_tracking_init (net );
9045+ /* safe for laundromat to run now */
9046+ spin_lock (& nn -> client_lock );
9047+ nn -> client_tracking_active = true;
9048+ spin_unlock (& nn -> client_lock );
90159049 if (nn -> track_reclaim_completes && nn -> reclaim_str_hashtbl_size == 0 )
90169050 goto skip_grace ;
90179051 printk (KERN_INFO "NFSD: starting %lld-second grace period (net %x)\n" ,
@@ -9060,6 +9094,9 @@ nfs4_state_shutdown_net(struct net *net)
90609094
90619095 shrinker_free (nn -> nfsd_client_shrinker );
90629096 cancel_work_sync (& nn -> nfsd_shrinker_work );
9097+ spin_lock (& nn -> client_lock );
9098+ nn -> client_tracking_active = false;
9099+ spin_unlock (& nn -> client_lock );
90639100 cancel_delayed_work_sync (& nn -> laundromat_work );
90649101 locks_end_grace (& nn -> nfsd4_manager );
90659102
0 commit comments