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
This commit is contained in:
parent
8e7393944d
commit
6001db296e
@ -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, SVCXPRT *xprt)
|
||||
#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, SVCXPRT *xprt)
|
||||
|
||||
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;
|
||||
|
@ -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 nfssvc_args *uap, struct ucred *cred)
|
||||
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 nfssvc_args *uap, struct ucred *cred)
|
||||
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);
|
||||
|
@ -102,7 +102,8 @@ sys_nfssvc(struct thread *td, struct nfssvc_args *uap)
|
||||
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)
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user