@@ -1210,6 +1210,8 @@ nfs4_put_stid(struct nfs4_stid *s)
12101210 return ;
12111211 }
12121212 idr_remove (& clp -> cl_stateids , s -> sc_stateid .si_opaque .so_id );
1213+ if (s -> sc_status & SC_STATUS_ADMIN_REVOKED )
1214+ atomic_dec (& s -> sc_client -> cl_admin_revoked );
12131215 nfs4_free_cpntf_statelist (clp -> net , s );
12141216 spin_unlock (& clp -> cl_lock );
12151217 s -> sc_free (s );
@@ -1529,6 +1531,8 @@ static void put_ol_stateid_locked(struct nfs4_ol_stateid *stp,
15291531 }
15301532
15311533 idr_remove (& clp -> cl_stateids , s -> sc_stateid .si_opaque .so_id );
1534+ if (s -> sc_status & SC_STATUS_ADMIN_REVOKED )
1535+ atomic_dec (& s -> sc_client -> cl_admin_revoked );
15321536 list_add (& stp -> st_locks , reaplist );
15331537}
15341538
@@ -1674,6 +1678,68 @@ static void release_openowner(struct nfs4_openowner *oo)
16741678 nfs4_put_stateowner (& oo -> oo_owner );
16751679}
16761680
1681+ static struct nfs4_stid * find_one_sb_stid (struct nfs4_client * clp ,
1682+ struct super_block * sb ,
1683+ unsigned int sc_types )
1684+ {
1685+ unsigned long id , tmp ;
1686+ struct nfs4_stid * stid ;
1687+
1688+ spin_lock (& clp -> cl_lock );
1689+ idr_for_each_entry_ul (& clp -> cl_stateids , stid , tmp , id )
1690+ if ((stid -> sc_type & sc_types ) &&
1691+ stid -> sc_status == 0 &&
1692+ stid -> sc_file -> fi_inode -> i_sb == sb ) {
1693+ refcount_inc (& stid -> sc_count );
1694+ break ;
1695+ }
1696+ spin_unlock (& clp -> cl_lock );
1697+ return stid ;
1698+ }
1699+
1700+ /**
1701+ * nfsd4_revoke_states - revoke all nfsv4 states associated with given filesystem
1702+ * @net: used to identify instance of nfsd (there is one per net namespace)
1703+ * @sb: super_block used to identify target filesystem
1704+ *
1705+ * All nfs4 states (open, lock, delegation, layout) held by the server instance
1706+ * and associated with a file on the given filesystem will be revoked resulting
1707+ * in any files being closed and so all references from nfsd to the filesystem
1708+ * being released. Thus nfsd will no longer prevent the filesystem from being
1709+ * unmounted.
1710+ *
1711+ * The clients which own the states will subsequently being notified that the
1712+ * states have been "admin-revoked".
1713+ */
1714+ void nfsd4_revoke_states (struct net * net , struct super_block * sb )
1715+ {
1716+ struct nfsd_net * nn = net_generic (net , nfsd_net_id );
1717+ unsigned int idhashval ;
1718+ unsigned int sc_types ;
1719+
1720+ sc_types = 0 ;
1721+
1722+ spin_lock (& nn -> client_lock );
1723+ for (idhashval = 0 ; idhashval < CLIENT_HASH_MASK ; idhashval ++ ) {
1724+ struct list_head * head = & nn -> conf_id_hashtbl [idhashval ];
1725+ struct nfs4_client * clp ;
1726+ retry :
1727+ list_for_each_entry (clp , head , cl_idhash ) {
1728+ struct nfs4_stid * stid = find_one_sb_stid (clp , sb ,
1729+ sc_types );
1730+ if (stid ) {
1731+ spin_unlock (& nn -> client_lock );
1732+ switch (stid -> sc_type ) {
1733+ }
1734+ nfs4_put_stid (stid );
1735+ spin_lock (& nn -> client_lock );
1736+ goto retry ;
1737+ }
1738+ }
1739+ }
1740+ spin_unlock (& nn -> client_lock );
1741+ }
1742+
16771743static inline int
16781744hash_sessionid (struct nfs4_sessionid * sessionid )
16791745{
@@ -2545,6 +2611,8 @@ static int client_info_show(struct seq_file *m, void *v)
25452611 }
25462612 seq_printf (m , "callback state: %s\n" , cb_state2str (clp -> cl_cb_state ));
25472613 seq_printf (m , "callback address: %pISpc\n" , & clp -> cl_cb_conn .cb_addr );
2614+ seq_printf (m , "admin-revoked states: %d\n" ,
2615+ atomic_read (& clp -> cl_admin_revoked ));
25482616 drop_client (clp );
25492617
25502618 return 0 ;
@@ -4058,6 +4126,8 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
40584126 }
40594127 if (!list_empty (& clp -> cl_revoked ))
40604128 seq -> status_flags |= SEQ4_STATUS_RECALLABLE_STATE_REVOKED ;
4129+ if (atomic_read (& clp -> cl_admin_revoked ))
4130+ seq -> status_flags |= SEQ4_STATUS_ADMIN_STATE_REVOKED ;
40614131 trace_nfsd_seq4_status (rqstp , seq );
40624132out_no_session :
40634133 if (conn )
@@ -4547,7 +4617,9 @@ nfsd4_verify_open_stid(struct nfs4_stid *s)
45474617{
45484618 __be32 ret = nfs_ok ;
45494619
4550- if (s -> sc_status & SC_STATUS_REVOKED )
4620+ if (s -> sc_status & SC_STATUS_ADMIN_REVOKED )
4621+ ret = nfserr_admin_revoked ;
4622+ else if (s -> sc_status & SC_STATUS_REVOKED )
45514623 ret = nfserr_deleg_revoked ;
45524624 else if (s -> sc_status & SC_STATUS_CLOSED )
45534625 ret = nfserr_bad_stateid ;
@@ -5136,6 +5208,11 @@ nfs4_check_deleg(struct nfs4_client *cl, struct nfsd4_open *open,
51365208 deleg = find_deleg_stateid (cl , & open -> op_delegate_stateid );
51375209 if (deleg == NULL )
51385210 goto out ;
5211+ if (deleg -> dl_stid .sc_status & SC_STATUS_ADMIN_REVOKED ) {
5212+ nfs4_put_stid (& deleg -> dl_stid );
5213+ status = nfserr_admin_revoked ;
5214+ goto out ;
5215+ }
51395216 if (deleg -> dl_stid .sc_status & SC_STATUS_REVOKED ) {
51405217 nfs4_put_stid (& deleg -> dl_stid );
51415218 status = nfserr_deleg_revoked ;
@@ -6443,6 +6520,8 @@ nfsd4_lookup_stateid(struct nfsd4_compound_state *cstate,
64436520 */
64446521 statusmask |= SC_STATUS_REVOKED ;
64456522
6523+ statusmask |= SC_STATUS_ADMIN_REVOKED ;
6524+
64466525 if (ZERO_STATEID (stateid ) || ONE_STATEID (stateid ) ||
64476526 CLOSE_STATEID (stateid ))
64486527 return nfserr_bad_stateid ;
@@ -6461,6 +6540,10 @@ nfsd4_lookup_stateid(struct nfsd4_compound_state *cstate,
64616540 nfs4_put_stid (stid );
64626541 return nfserr_deleg_revoked ;
64636542 }
6543+ if (stid -> sc_status & SC_STATUS_ADMIN_REVOKED ) {
6544+ nfs4_put_stid (stid );
6545+ return nfserr_admin_revoked ;
6546+ }
64646547 * s = stid ;
64656548 return nfs_ok ;
64666549}
0 commit comments