diff options
-rw-r--r-- | sys/fs/nfs/nfs_var.h | 1 | ||||
-rw-r--r-- | sys/fs/nfsserver/nfs_nfsdkrpc.c | 2 | ||||
-rw-r--r-- | sys/fs/nfsserver/nfs_nfsdport.c | 39 | ||||
-rw-r--r-- | sys/fs/nfsserver/nfs_nfsdstate.c | 8 | ||||
-rw-r--r-- | sys/nfs/nfs_nfssvc.c | 2 | ||||
-rw-r--r-- | sys/nfs/nfssvc.h | 1 |
6 files changed, 51 insertions, 2 deletions
diff --git a/sys/fs/nfs/nfs_var.h b/sys/fs/nfs/nfs_var.h index 2dbbdda..03365fc 100644 --- a/sys/fs/nfs/nfs_var.h +++ b/sys/fs/nfs/nfs_var.h @@ -573,6 +573,7 @@ int nfsvno_advlock(vnode_t, int, u_int64_t, u_int64_t, NFSPROC_T *); int nfsrv_v4rootexport(void *, struct ucred *, NFSPROC_T *); int nfsvno_testexp(struct nfsrv_descript *, struct nfsexstuff *); uint32_t nfsrv_hashfh(fhandle_t *); +void nfsrv_backupstable(void); /* nfs_commonkrpc.c */ int newnfs_nmcancelreqs(struct nfsmount *); diff --git a/sys/fs/nfsserver/nfs_nfsdkrpc.c b/sys/fs/nfsserver/nfs_nfsdkrpc.c index 20ea1cd..2181207 100644 --- a/sys/fs/nfsserver/nfs_nfsdkrpc.c +++ b/sys/fs/nfsserver/nfs_nfsdkrpc.c @@ -97,6 +97,7 @@ static int nfs_proc(struct nfsrv_descript *, u_int32_t, struct socket *, extern u_long sb_max_adj; extern int newnfs_numnfsd; +extern struct proc *nfsd_master_proc; /* * NFS server system calls @@ -465,6 +466,7 @@ nfsrvd_init(int terminating) NFSD_LOCK_ASSERT(); if (terminating) { + nfsd_master_proc = NULL; NFSD_UNLOCK(); svcpool_destroy(nfsrvd_pool); nfsrvd_pool = NULL; diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c index efa7ff4..035212f 100644 --- a/sys/fs/nfsserver/nfs_nfsdport.c +++ b/sys/fs/nfsserver/nfs_nfsdport.c @@ -58,6 +58,10 @@ struct mtx nfs_cache_mutex; struct mtx nfs_v4root_mutex; struct nfsrvfh nfs_rootfh, nfs_pubfh; int nfs_pubfhset = 0, nfs_rootfhset = 0; +struct proc *nfsd_master_proc = NULL; +static pid_t nfsd_master_pid = (pid_t)-1; +static char nfsd_master_comm[MAXCOMLEN + 1]; +static struct timeval nfsd_master_start; static uint32_t nfsv4_sysid = 0; static int nfssvc_srvcall(struct thread *, struct nfssvc_args *, @@ -2905,6 +2909,7 @@ nfssvc_srvcall(struct thread *p, struct nfssvc_args *uap, struct ucred *cred) struct nameidata nd; vnode_t vp; int error = EINVAL; + struct proc *procp; if (uap->flag & NFSSVC_PUBLICFH) { NFSBZERO((caddr_t)&nfs_pubfh.nfsrvfh_data, @@ -2975,6 +2980,14 @@ nfssvc_srvcall(struct thread *p, struct nfssvc_args *uap, struct ucred *cred) CAST_USER_ADDR_T(dumplocklist.ndllck_list), len); free((caddr_t)dumplocks, M_TEMP); } + } else if (uap->flag & NFSSVC_BACKUPSTABLE) { + procp = p->td_proc; + PROC_LOCK(procp); + nfsd_master_pid = procp->p_pid; + bcopy(procp->p_comm, nfsd_master_comm, MAXCOMLEN + 1); + nfsd_master_start = procp->p_stats->p_start; + nfsd_master_proc = procp; + PROC_UNLOCK(procp); } return (error); } @@ -3030,6 +3043,32 @@ nfsrv_hashfh(fhandle_t *fhp) return (hashval); } +/* + * Signal the userland master nfsd to backup the stable restart file. + */ +void +nfsrv_backupstable(void) +{ + struct proc *procp; + + if (nfsd_master_proc != NULL) { + procp = pfind(nfsd_master_pid); + /* Try to make sure it is the correct process. */ + if (procp == nfsd_master_proc && + procp->p_stats->p_start.tv_sec == + nfsd_master_start.tv_sec && + procp->p_stats->p_start.tv_usec == + nfsd_master_start.tv_usec && + strcmp(procp->p_comm, nfsd_master_comm) == 0) + psignal(procp, SIGUSR2); + else + nfsd_master_proc = NULL; + + if (procp != NULL) + PROC_UNLOCK(procp); + } +} + extern int (*nfsd_call_nfsd)(struct thread *, struct nfssvc_args *); /* diff --git a/sys/fs/nfsserver/nfs_nfsdstate.c b/sys/fs/nfsserver/nfs_nfsdstate.c index 1008e26..a480c8e 100644 --- a/sys/fs/nfsserver/nfs_nfsdstate.c +++ b/sys/fs/nfsserver/nfs_nfsdstate.c @@ -577,6 +577,7 @@ nfsrv_adminrevoke(struct nfsd_clid *revokep, NFSPROC_T *p) * Now, write out the revocation record */ nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p); + nfsrv_backupstable(); /* * and clear out the state, marking the clientid revoked. @@ -2988,8 +2989,10 @@ nfsrv_openupdate(vnode_t vp, struct nfsstate *new_stp, nfsquad_t clientid, * If the client just confirmed its first open, write a timestamp * to the stable storage file. */ - if (gotstate) + if (gotstate != 0) { nfsrv_writestable(client, len, NFSNST_NEWSTATE, p); + nfsrv_backupstable(); + } return (error); } @@ -4132,6 +4135,7 @@ nfsrv_updatestable(NFSPROC_T *p) LIST_REMOVE(sp, nst_list); free((caddr_t)sp, M_TEMP); } + nfsrv_backupstable(); } /* @@ -4266,6 +4270,7 @@ nfsrv_clientconflict(struct nfsclient *clp, int *haslockp, vnode_t vp, * Ok, we can expire the conflicting client. */ nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p); + nfsrv_backupstable(); nfsrv_cleanclient(clp, p); nfsrv_freedeleglist(&clp->lc_deleg); nfsrv_freedeleglist(&clp->lc_olddeleg); @@ -4441,6 +4446,7 @@ nfsrv_delegconflict(struct nfsstate *stp, int *haslockp, NFSPROC_T *p, * sleep without the state changing. */ nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p); + nfsrv_backupstable(); if (clp->lc_expiry < NFSD_MONOSEC) { nfsrv_cleanclient(clp, p); nfsrv_freedeleglist(&clp->lc_deleg); diff --git a/sys/nfs/nfs_nfssvc.c b/sys/nfs/nfs_nfssvc.c index b9186be..cb1f37a 100644 --- a/sys/nfs/nfs_nfssvc.c +++ b/sys/nfs/nfs_nfssvc.c @@ -99,7 +99,7 @@ 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_DUMPCLIENTS | NFSSVC_DUMPLOCKS | NFSSVC_BACKUPSTABLE)) && nfsd_call_nfsd != NULL) error = (*nfsd_call_nfsd)(td, uap); if (error == EINTR || error == ERESTART) diff --git a/sys/nfs/nfssvc.h b/sys/nfs/nfssvc.h index 5578240..d756dbf 100644 --- a/sys/nfs/nfssvc.h +++ b/sys/nfs/nfssvc.h @@ -63,5 +63,6 @@ #define NFSSVC_NFSCBD 0x00100000 #define NFSSVC_CBADDSOCK 0x00200000 #define NFSSVC_GETSTATS 0x00400000 +#define NFSSVC_BACKUPSTABLE 0x00800000 #endif /* _NFS_NFSSVC_H */ |