summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/fs/nfs/nfs_var.h1
-rw-r--r--sys/fs/nfsserver/nfs_nfsdkrpc.c2
-rw-r--r--sys/fs/nfsserver/nfs_nfsdport.c39
-rw-r--r--sys/fs/nfsserver/nfs_nfsdstate.c8
-rw-r--r--sys/nfs/nfs_nfssvc.c2
-rw-r--r--sys/nfs/nfssvc.h1
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 */
OpenPOWER on IntegriCloud