Author: rmacklem
Date: Sat Dec  1 01:07:51 2012
New Revision: 243738
URL: http://svnweb.freebsd.org/changeset/base/243738

Log:
  MFC: r241561
  Add two new options to the nfssvc(2) syscall that allow
  processes running as root to suspend/resume execution
  of the kernel nfsd threads. An earlier version of this
  patch was tested by Vincent Hoffman (vince at unsane.co.uk)
  and John Hickey (jh at deterlab.net).

Modified:
  stable/9/sys/fs/nfsserver/nfs_nfsdkrpc.c
  stable/9/sys/fs/nfsserver/nfs_nfsdport.c
  stable/9/sys/nfs/nfs_nfssvc.c
  stable/9/sys/nfs/nfssvc.h
Directory Properties:
  stable/9/sys/   (props changed)
  stable/9/sys/fs/   (props changed)

Modified: stable/9/sys/fs/nfsserver/nfs_nfsdkrpc.c
==============================================================================
--- stable/9/sys/fs/nfsserver/nfs_nfsdkrpc.c    Sat Dec  1 00:56:19 2012        
(r243737)
+++ stable/9/sys/fs/nfsserver/nfs_nfsdkrpc.c    Sat Dec  1 01:07:51 2012        
(r243738)
@@ -45,6 +45,8 @@ __FBSDID("$FreeBSD$");
 #include <security/mac/mac_framework.h>
 
 NFSDLOCKMUTEX;
+NFSV4ROOTLOCKMUTEX;
+struct nfsv4lock nfsd_suspend_lock;
 
 /*
  * Mapping of old NFS Version 2 RPC numbers to generic numbers.
@@ -221,9 +223,24 @@ nfssvc_program(struct svc_req *rqst, SVC
 #ifdef MAC
                mac_cred_associate_nfsd(nd.nd_cred);
 #endif
+               /*
+                * Get a refcnt (shared lock) on nfsd_suspend_lock.
+                * NFSSVC_SUSPENDNFSD will take an exclusive lock on
+                * nfsd_suspend_lock to suspend these threads.
+                * This must be done here, before the check of
+                * nfsv4root exports by nfsvno_v4rootexport().
+                */
+               NFSLOCKV4ROOTMUTEX();
+               nfsv4_getref(&nfsd_suspend_lock, NULL, NFSV4ROOTLOCKMUTEXPTR,
+                   NULL);
+               NFSUNLOCKV4ROOTMUTEX();
+
                if ((nd.nd_flag & ND_NFSV4) != 0) {
                        nd.nd_repstat = nfsvno_v4rootexport(&nd);
                        if (nd.nd_repstat != 0) {
+                               NFSLOCKV4ROOTMUTEX();
+                               nfsv4_relref(&nfsd_suspend_lock);
+                               NFSUNLOCKV4ROOTMUTEX();
                                svcerr_weakauth(rqst);
                                svc_freereq(rqst);
                                m_freem(nd.nd_mrep);
@@ -233,6 +250,9 @@ nfssvc_program(struct svc_req *rqst, SVC
 
                cacherep = nfs_proc(&nd, rqst->rq_xid, xprt->xp_socket,
                    xprt->xp_sockref, &rp);
+               NFSLOCKV4ROOTMUTEX();
+               nfsv4_relref(&nfsd_suspend_lock);
+               NFSUNLOCKV4ROOTMUTEX();
        } else {
                NFSMGET(nd.nd_mreq);
                nd.nd_mreq->m_len = 0;

Modified: stable/9/sys/fs/nfsserver/nfs_nfsdport.c
==============================================================================
--- stable/9/sys/fs/nfsserver/nfs_nfsdport.c    Sat Dec  1 00:56:19 2012        
(r243737)
+++ stable/9/sys/fs/nfsserver/nfs_nfsdport.c    Sat Dec  1 01:07:51 2012        
(r243738)
@@ -57,6 +57,7 @@ extern struct mount nfsv4root_mnt;
 extern struct nfsrv_stablefirst nfsrv_stablefirst;
 extern void (*nfsd_call_servertimer)(void);
 extern SVCPOOL *nfsrvd_pool;
+extern struct nfsv4lock nfsd_suspend_lock;
 struct vfsoptlist nfsv4root_opt, nfsv4root_newopt;
 NFSDLOCKMUTEX;
 struct mtx nfs_cache_mutex;
@@ -3104,8 +3105,9 @@ nfssvc_srvcall(struct thread *p, struct 
        struct nfsd_dumplocks *dumplocks;
        struct nameidata nd;
        vnode_t vp;
-       int error = EINVAL;
+       int error = EINVAL, igotlock;
        struct proc *procp;
+       static int suspend_nfsd = 0;
 
        if (uap->flag & NFSSVC_PUBLICFH) {
                NFSBZERO((caddr_t)&nfs_pubfh.nfsrvfh_data,
@@ -3184,6 +3186,26 @@ nfssvc_srvcall(struct thread *p, struct 
                nfsd_master_start = procp->p_stats->p_start;
                nfsd_master_proc = procp;
                PROC_UNLOCK(procp);
+       } else if ((uap->flag & NFSSVC_SUSPENDNFSD) != 0) {
+               NFSLOCKV4ROOTMUTEX();
+               if (suspend_nfsd == 0) {
+                       /* Lock out all nfsd threads */
+                       do {
+                               igotlock = nfsv4_lock(&nfsd_suspend_lock, 1,
+                                   NULL, NFSV4ROOTLOCKMUTEXPTR, NULL);
+                       } while (igotlock == 0 && suspend_nfsd == 0);
+                       suspend_nfsd = 1;
+               }
+               NFSUNLOCKV4ROOTMUTEX();
+               error = 0;
+       } else if ((uap->flag & NFSSVC_RESUMENFSD) != 0) {
+               NFSLOCKV4ROOTMUTEX();
+               if (suspend_nfsd != 0) {
+                       nfsv4_unlock(&nfsd_suspend_lock, 0);
+                       suspend_nfsd = 0;
+               }
+               NFSUNLOCKV4ROOTMUTEX();
+               error = 0;
        }
 
        NFSEXITCODE(error);

Modified: stable/9/sys/nfs/nfs_nfssvc.c
==============================================================================
--- stable/9/sys/nfs/nfs_nfssvc.c       Sat Dec  1 00:56:19 2012        
(r243737)
+++ stable/9/sys/nfs/nfs_nfssvc.c       Sat Dec  1 01:07:51 2012        
(r243738)
@@ -102,7 +102,8 @@ sys_nfssvc(struct thread *td, struct nfs
        else if ((uap->flag & (NFSSVC_NFSDNFSD | NFSSVC_NFSDADDSOCK |
            NFSSVC_PUBLICFH | NFSSVC_V4ROOTEXPORT | NFSSVC_NOPUBLICFH |
            NFSSVC_STABLERESTART | NFSSVC_ADMINREVOKE |
-           NFSSVC_DUMPCLIENTS | NFSSVC_DUMPLOCKS | NFSSVC_BACKUPSTABLE)) &&
+           NFSSVC_DUMPCLIENTS | NFSSVC_DUMPLOCKS | NFSSVC_BACKUPSTABLE |
+           NFSSVC_SUSPENDNFSD | NFSSVC_RESUMENFSD)) &&
            nfsd_call_nfsd != NULL)
                error = (*nfsd_call_nfsd)(td, uap);
        if (error == EINTR || error == ERESTART)

Modified: stable/9/sys/nfs/nfssvc.h
==============================================================================
--- stable/9/sys/nfs/nfssvc.h   Sat Dec  1 00:56:19 2012        (r243737)
+++ stable/9/sys/nfs/nfssvc.h   Sat Dec  1 01:07:51 2012        (r243738)
@@ -66,5 +66,7 @@
 #define        NFSSVC_BACKUPSTABLE     0x00800000
 #define        NFSSVC_ZEROCLTSTATS     0x01000000      /* modifier for 
GETSTATS */
 #define        NFSSVC_ZEROSRVSTATS     0x02000000      /* modifier for 
GETSTATS */
+#define        NFSSVC_SUSPENDNFSD      0x04000000
+#define        NFSSVC_RESUMENFSD       0x08000000
 
 #endif /* _NFS_NFSSVC_H */
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to