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