Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 14 Oct 2012 22:33:17 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r241561 - in head/sys: fs/nfsserver nfs
Message-ID:  <201210142233.q9EMXHvG055801@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Sun Oct 14 22:33:17 2012
New Revision: 241561
URL: http://svn.freebsd.org/changeset/base/241561

Log:
  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).
  
  Reviewed by:	kib
  MFC after:	2 weeks

Modified:
  head/sys/fs/nfsserver/nfs_nfsdkrpc.c
  head/sys/fs/nfsserver/nfs_nfsdport.c
  head/sys/nfs/nfs_nfssvc.c
  head/sys/nfs/nfssvc.h

Modified: head/sys/fs/nfsserver/nfs_nfsdkrpc.c
==============================================================================
--- head/sys/fs/nfsserver/nfs_nfsdkrpc.c	Sun Oct 14 22:28:56 2012	(r241560)
+++ head/sys/fs/nfsserver/nfs_nfsdkrpc.c	Sun Oct 14 22:33:17 2012	(r241561)
@@ -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: head/sys/fs/nfsserver/nfs_nfsdport.c
==============================================================================
--- head/sys/fs/nfsserver/nfs_nfsdport.c	Sun Oct 14 22:28:56 2012	(r241560)
+++ head/sys/fs/nfsserver/nfs_nfsdport.c	Sun Oct 14 22:33:17 2012	(r241561)
@@ -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;
@@ -3095,8 +3096,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,
@@ -3175,6 +3177,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: head/sys/nfs/nfs_nfssvc.c
==============================================================================
--- head/sys/nfs/nfs_nfssvc.c	Sun Oct 14 22:28:56 2012	(r241560)
+++ head/sys/nfs/nfs_nfssvc.c	Sun Oct 14 22:33:17 2012	(r241561)
@@ -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: head/sys/nfs/nfssvc.h
==============================================================================
--- head/sys/nfs/nfssvc.h	Sun Oct 14 22:28:56 2012	(r241560)
+++ head/sys/nfs/nfssvc.h	Sun Oct 14 22:33:17 2012	(r241561)
@@ -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 */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201210142233.q9EMXHvG055801>