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);