Print this page
Fix NFS design problems re. multiple zone keys
Make NFS server zone-specific data all have the same lifetime
Fix rfs4_clean_state_exi
Fix exi_cache_reclaim
Fix mistakes in zone keys work
More fixes re. exi_zoneid and exi_tree
(danmcd -> Keep some ASSERT()s around for readability.)
*** 114,123 ****
--- 114,126 ----
static struct modlinkage modlinkage = {
MODREV_1, (void *)&modlmisc, NULL
};
zone_key_t nfssrv_zone_key;
+ list_t nfssrv_globals_list;
+ krwlock_t nfssrv_globals_rwl;
+
kmem_cache_t *nfs_xuio_cache;
int nfs_loaned_buffers = 0;
int
_init(void)
*** 199,210 ****
bool_t, bool_t *);
static char *client_name(struct svc_req *req);
static char *client_addr(struct svc_req *req, char *buf);
extern int sec_svc_getcred(struct svc_req *, cred_t *cr, char **, int *);
extern bool_t sec_svc_inrootlist(int, caddr_t, int, caddr_t *);
! static void *nfs_srv_zone_init(zoneid_t);
! static void nfs_srv_zone_fini(zoneid_t, void *);
#define NFSLOG_COPY_NETBUF(exi, xprt, nb) { \
(nb)->maxlen = (xprt)->xp_rtaddr.maxlen; \
(nb)->len = (xprt)->xp_rtaddr.len; \
(nb)->buf = kmem_alloc((nb)->len, KM_SLEEP); \
--- 202,214 ----
bool_t, bool_t *);
static char *client_name(struct svc_req *req);
static char *client_addr(struct svc_req *req, char *buf);
extern int sec_svc_getcred(struct svc_req *, cred_t *cr, char **, int *);
extern bool_t sec_svc_inrootlist(int, caddr_t, int, caddr_t *);
! static void *nfs_server_zone_init(zoneid_t);
! static void nfs_server_zone_fini(zoneid_t, void *);
! static void nfs_server_zone_shutdown(zoneid_t, void *);
#define NFSLOG_COPY_NETBUF(exi, xprt, nb) { \
(nb)->maxlen = (xprt)->xp_rtaddr.maxlen; \
(nb)->len = (xprt)->xp_rtaddr.len; \
(nb)->buf = kmem_alloc((nb)->len, KM_SLEEP); \
*** 261,270 ****
--- 265,283 ----
nvlist_t *rfs4_dss_paths, *rfs4_dss_oldpaths;
int rfs4_dispatch(struct rpcdisp *, struct svc_req *, SVCXPRT *, char *);
bool_t rfs4_minorvers_mismatch(struct svc_req *, SVCXPRT *, void *);
+ nfs_globals_t *
+ nfs_srv_getzg(void)
+ {
+ nfs_globals_t *ng;
+
+ ng = zone_getspecific(nfssrv_zone_key, curzone);
+ return (ng);
+ }
+
/*
* Will be called at the point the server pool is being unregistered
* from the pool list. From that point onwards, the pool is waiting
* to be drained and as such the server state is stale and pertains
* to the old instantiation of the NFS server pool.
*** 272,282 ****
void
nfs_srv_offline(void)
{
nfs_globals_t *ng;
! ng = zone_getspecific(nfssrv_zone_key, curzone);
mutex_enter(&ng->nfs_server_upordown_lock);
if (ng->nfs_server_upordown == NFS_SERVER_RUNNING) {
ng->nfs_server_upordown = NFS_SERVER_OFFLINE;
}
--- 285,295 ----
void
nfs_srv_offline(void)
{
nfs_globals_t *ng;
! ng = nfs_srv_getzg();
mutex_enter(&ng->nfs_server_upordown_lock);
if (ng->nfs_server_upordown == NFS_SERVER_RUNNING) {
ng->nfs_server_upordown = NFS_SERVER_OFFLINE;
}
*** 309,319 ****
}
static void
nfs_srv_shutdown_all(int quiesce)
{
! nfs_globals_t *ng = zone_getspecific(nfssrv_zone_key, curzone);
mutex_enter(&ng->nfs_server_upordown_lock);
if (quiesce) {
if (ng->nfs_server_upordown == NFS_SERVER_RUNNING ||
ng->nfs_server_upordown == NFS_SERVER_OFFLINE) {
--- 322,332 ----
}
static void
nfs_srv_shutdown_all(int quiesce)
{
! nfs_globals_t *ng = nfs_srv_getzg();
mutex_enter(&ng->nfs_server_upordown_lock);
if (quiesce) {
if (ng->nfs_server_upordown == NFS_SERVER_RUNNING ||
ng->nfs_server_upordown == NFS_SERVER_OFFLINE) {
*** 424,441 ****
#ifdef lint
model = model; /* STRUCT macros don't always refer to it */
#endif
! ng = zone_getspecific(nfssrv_zone_key, curzone);
STRUCT_SET_HANDLE(uap, model, arg);
/* Check privileges in nfssys() */
if ((fp = getf(STRUCT_FGET(uap, fd))) == NULL)
return (EBADF);
/*
* Set read buffer size to rsize
* and add room for RPC headers.
*/
readsize = nfs3tsize() + (RPC_MAXDATASIZE - NFS_MAXDATA);
--- 437,458 ----
#ifdef lint
model = model; /* STRUCT macros don't always refer to it */
#endif
! ng = nfs_srv_getzg();
STRUCT_SET_HANDLE(uap, model, arg);
/* Check privileges in nfssys() */
if ((fp = getf(STRUCT_FGET(uap, fd))) == NULL)
return (EBADF);
+ /* Setup global file handle in nfs_export */
+ if ((error = nfs_export_get_rootfh(ng)) != 0)
+ return (error);
+
/*
* Set read buffer size to rsize
* and add room for RPC headers.
*/
readsize = nfs3tsize() + (RPC_MAXDATASIZE - NFS_MAXDATA);
*** 550,560 ****
(rsa->nfs_versmax > NFS_VERSMAX)) {
rsa->nfs_versmin = NFS_VERSMIN_DEFAULT;
rsa->nfs_versmax = NFS_VERSMAX_DEFAULT;
}
! ng = zone_getspecific(nfssrv_zone_key, curzone);
ng->nfs_versmin = rsa->nfs_versmin;
ng->nfs_versmax = rsa->nfs_versmax;
/* Set the versions in the callout table */
__nfs_sc_rdma[0].sc_versmin = rsa->nfs_versmin;
--- 567,577 ----
(rsa->nfs_versmax > NFS_VERSMAX)) {
rsa->nfs_versmin = NFS_VERSMIN_DEFAULT;
rsa->nfs_versmax = NFS_VERSMAX_DEFAULT;
}
! ng = nfs_srv_getzg();
ng->nfs_versmin = rsa->nfs_versmin;
ng->nfs_versmax = rsa->nfs_versmax;
/* Set the versions in the callout table */
__nfs_sc_rdma[0].sc_versmin = rsa->nfs_versmin;
*** 2545,2563 ****
* - initialize the version 3 write verifier
*/
void
nfs_srvinit(void)
{
- /* NFS server zone-specific global variables */
- zone_key_create(&nfssrv_zone_key, nfs_srv_zone_init,
- NULL, nfs_srv_zone_fini);
nfs_exportinit();
rfs_srvrinit();
rfs3_srvrinit();
rfs4_srvrinit();
nfsauth_init();
}
/*
* NFS Server finalization routine. This routine is called to cleanup the
* initialization work previously performed if the NFS server module could
--- 2562,2590 ----
* - initialize the version 3 write verifier
*/
void
nfs_srvinit(void)
{
+ /* Truly global stuff in this module (not per zone) */
+ rw_init(&nfssrv_globals_rwl, NULL, RW_DEFAULT, NULL);
+ list_create(&nfssrv_globals_list, sizeof (nfs_globals_t),
+ offsetof (nfs_globals_t, nfs_g_link));
+
+ /* The order here is important */
nfs_exportinit();
rfs_srvrinit();
rfs3_srvrinit();
rfs4_srvrinit();
nfsauth_init();
+
+ /*
+ * NFS server zone-specific global variables
+ * Note the zone_init is called for the GZ here.
+ */
+ zone_key_create(&nfssrv_zone_key, nfs_server_zone_init,
+ nfs_server_zone_shutdown, nfs_server_zone_fini);
}
/*
* NFS Server finalization routine. This routine is called to cleanup the
* initialization work previously performed if the NFS server module could
*** 2564,2585 ****
* not be loaded correctly.
*/
void
nfs_srvfini(void)
{
nfsauth_fini();
rfs4_srvrfini();
rfs3_srvrfini();
rfs_srvrfini();
nfs_exportfini();
! (void) zone_key_delete(nfssrv_zone_key);
}
! /* ARGSUSED */
static void *
! nfs_srv_zone_init(zoneid_t zoneid)
{
nfs_globals_t *ng;
ng = kmem_zalloc(sizeof (*ng), KM_SLEEP);
--- 2591,2634 ----
* not be loaded correctly.
*/
void
nfs_srvfini(void)
{
+
+ /*
+ * NFS server zone-specific global variables
+ * Note the zone_fini is called for the GZ here.
+ */
+ (void) zone_key_delete(nfssrv_zone_key);
+
+ /* The order here is important (reverse of init) */
nfsauth_fini();
rfs4_srvrfini();
rfs3_srvrfini();
rfs_srvrfini();
nfs_exportfini();
! /* Truly global stuff in this module (not per zone) */
! list_destroy(&nfssrv_globals_list);
! rw_destroy(&nfssrv_globals_rwl);
}
! /*
! * Zone init, shutdown, fini functions for the NFS server
! *
! * This design is careful to create the entire hierarhcy of
! * NFS server "globals" (including those created by various
! * per-module *_zone_init functions, etc.) so that all these
! * objects have exactly the same lifetime.
! *
! * These objects are also kept on a list for two reasons:
! * 1: It makes finding these in mdb _much_ easier.
! * 2: It allows operating across all zone globals for
! * functions like nfs_auth.c:exi_cache_reclaim
! */
static void *
! nfs_server_zone_init(zoneid_t zoneid)
{
nfs_globals_t *ng;
ng = kmem_zalloc(sizeof (*ng), KM_SLEEP);
*** 2591,2610 ****
mutex_init(&ng->nfs_server_upordown_lock, NULL, MUTEX_DEFAULT, NULL);
cv_init(&ng->nfs_server_upordown_cv, NULL, CV_DEFAULT, NULL);
mutex_init(&ng->rdma_wait_mutex, NULL, MUTEX_DEFAULT, NULL);
cv_init(&ng->rdma_wait_cv, NULL, CV_DEFAULT, NULL);
return (ng);
}
/* ARGSUSED */
static void
! nfs_srv_zone_fini(zoneid_t zoneid, void *data)
{
nfs_globals_t *ng;
ng = (nfs_globals_t *)data;
mutex_destroy(&ng->nfs_server_upordown_lock);
cv_destroy(&ng->nfs_server_upordown_cv);
mutex_destroy(&ng->rdma_wait_mutex);
cv_destroy(&ng->rdma_wait_cv);
--- 2640,2706 ----
mutex_init(&ng->nfs_server_upordown_lock, NULL, MUTEX_DEFAULT, NULL);
cv_init(&ng->nfs_server_upordown_cv, NULL, CV_DEFAULT, NULL);
mutex_init(&ng->rdma_wait_mutex, NULL, MUTEX_DEFAULT, NULL);
cv_init(&ng->rdma_wait_cv, NULL, CV_DEFAULT, NULL);
+ ng->nfs_zoneid = zoneid;
+
+ /*
+ * Order here is important.
+ * export init must precede srv init calls.
+ */
+ nfs_export_zone_init(ng);
+ rfs_srv_zone_init(ng);
+ rfs3_srv_zone_init(ng);
+ rfs4_srv_zone_init(ng);
+ nfsauth_zone_init(ng);
+
+ rw_enter(&nfssrv_globals_rwl, RW_WRITER);
+ list_insert_tail(&nfssrv_globals_list, ng);
+ rw_exit(&nfssrv_globals_rwl);
+
return (ng);
}
/* ARGSUSED */
static void
! nfs_server_zone_shutdown(zoneid_t zoneid, void *data)
{
nfs_globals_t *ng;
ng = (nfs_globals_t *)data;
+
+ /*
+ * Order is like _fini, but only
+ * some modules need this hook.
+ */
+ nfsauth_zone_shutdown(ng);
+ nfs_export_zone_shutdown(ng);
+ }
+
+ /* ARGSUSED */
+ static void
+ nfs_server_zone_fini(zoneid_t zoneid, void *data)
+ {
+ nfs_globals_t *ng;
+
+ ng = (nfs_globals_t *)data;
+
+ rw_enter(&nfssrv_globals_rwl, RW_WRITER);
+ list_remove(&nfssrv_globals_list, ng);
+ rw_exit(&nfssrv_globals_rwl);
+
+ /*
+ * Order here is important.
+ * reverse order from init
+ */
+ nfsauth_zone_fini(ng);
+ rfs4_srv_zone_fini(ng);
+ rfs3_srv_zone_fini(ng);
+ rfs_srv_zone_fini(ng);
+ nfs_export_zone_fini(ng);
+
mutex_destroy(&ng->nfs_server_upordown_lock);
cv_destroy(&ng->nfs_server_upordown_cv);
mutex_destroy(&ng->rdma_wait_mutex);
cv_destroy(&ng->rdma_wait_cv);