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

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/nfs/nfs_auth.c
          +++ new/usr/src/uts/common/fs/nfs/nfs_auth.c
↓ open down ↓ 44 lines elided ↑ open up ↑
  45   45  #include <rpc/auth.h>
  46   46  #include <rpc/clnt.h>
  47   47  
  48   48  #include <nfs/nfs.h>
  49   49  #include <nfs/export.h>
  50   50  #include <nfs/nfs_clnt.h>
  51   51  #include <nfs/auth.h>
  52   52  
  53   53  static struct kmem_cache *exi_cache_handle;
  54   54  static void exi_cache_reclaim(void *);
       55 +static void exi_cache_reclaim_zone(nfs_globals_t *);
  55   56  static void exi_cache_trim(struct exportinfo *exi);
  56      -static void *nfsauth_zone_init(zoneid_t);
  57      -static void nfsauth_zone_shutdown(zoneid_t zoneid, void *data);
  58      -static void nfsauth_zone_fini(zoneid_t, void *);
  59   57  
  60   58  extern pri_t minclsyspri;
  61   59  
  62   60  /* NFS auth cache statistics */
  63   61  volatile uint_t nfsauth_cache_hit;
  64   62  volatile uint_t nfsauth_cache_miss;
  65   63  volatile uint_t nfsauth_cache_refresh;
  66   64  volatile uint_t nfsauth_cache_reclaim;
  67   65  volatile uint_t exi_cache_auth_reclaim_failed;
  68   66  volatile uint_t exi_cache_clnt_reclaim_failed;
↓ open down ↓ 100 lines elided ↑ open up ↑
 169  167          struct auth_cache               *refreshq_dead_entries;
 170  168          nfsauth_refreshq_thread_state_t refreshq_thread_state;
 171  169  
 172  170  } nfsauth_globals_t;
 173  171  
 174  172  static void nfsauth_free_node(struct auth_cache *);
 175  173  static void nfsauth_refresh_thread(nfsauth_globals_t *);
 176  174  
 177  175  static int nfsauth_cache_compar(const void *, const void *);
 178  176  
 179      -static zone_key_t       nfsauth_zone_key;
      177 +static nfsauth_globals_t *
      178 +nfsauth_get_zg(void)
      179 +{
      180 +        nfs_globals_t *ng = zone_getspecific(nfssrv_zone_key, curzone);
      181 +        nfsauth_globals_t *nag = ng->nfs_auth;
      182 +        ASSERT(nag != NULL);
      183 +        return (nag);
      184 +}
 180  185  
 181  186  void
 182  187  mountd_args(uint_t did)
 183  188  {
 184  189          nfsauth_globals_t *nag;
 185  190  
 186      -        nag = zone_getspecific(nfsauth_zone_key, curzone);
      191 +        nag = nfsauth_get_zg();
 187  192          mutex_enter(&nag->mountd_lock);
 188  193          if (nag->mountd_dh != NULL)
 189  194                  door_ki_rele(nag->mountd_dh);
 190  195          nag->mountd_dh = door_ki_lookup(did);
 191  196          mutex_exit(&nag->mountd_lock);
 192  197  }
 193  198  
 194  199  void
 195  200  nfsauth_init(void)
 196  201  {
 197      -        zone_key_create(&nfsauth_zone_key, nfsauth_zone_init,
 198      -            nfsauth_zone_shutdown, nfsauth_zone_fini);
 199      -
 200  202          exi_cache_handle = kmem_cache_create("exi_cache_handle",
 201  203              sizeof (struct auth_cache), 0, NULL, NULL,
 202  204              exi_cache_reclaim, NULL, NULL, 0);
 203  205  }
 204  206  
 205  207  void
 206  208  nfsauth_fini(void)
 207  209  {
 208  210          kmem_cache_destroy(exi_cache_handle);
 209  211  }
 210  212  
 211      -/*ARGSUSED*/
 212      -static void *
 213      -nfsauth_zone_init(zoneid_t zoneid)
      213 +void
      214 +nfsauth_zone_init(nfs_globals_t *ng)
 214  215  {
 215  216          nfsauth_globals_t *nag;
 216  217  
 217  218          nag = kmem_zalloc(sizeof (*nag), KM_SLEEP);
 218  219  
 219  220          /*
 220  221           * mountd can be restarted by smf(5).  We need to make sure
 221  222           * the updated door handle will safely make it to mountd_dh.
 222  223           */
 223  224          mutex_init(&nag->mountd_lock, NULL, MUTEX_DEFAULT, NULL);
 224  225          mutex_init(&nag->refreshq_lock, NULL, MUTEX_DEFAULT, NULL);
 225  226          list_create(&nag->refreshq_queue, sizeof (refreshq_exi_node_t),
 226  227              offsetof(refreshq_exi_node_t, ren_node));
 227  228          cv_init(&nag->refreshq_cv, NULL, CV_DEFAULT, NULL);
 228  229          nag->refreshq_thread_state = REFRESHQ_THREAD_NEED_CREATE;
 229  230  
 230      -        return (nag);
      231 +        ng->nfs_auth = nag;
 231  232  }
 232  233  
 233      -/*ARGSUSED*/
 234      -static void
 235      -nfsauth_zone_shutdown(zoneid_t zoneid, void *data)
      234 +void
      235 +nfsauth_zone_shutdown(nfs_globals_t *ng)
 236  236  {
 237  237          refreshq_exi_node_t     *ren;
 238      -        nfsauth_globals_t       *nag = data;
      238 +        nfsauth_globals_t       *nag = ng->nfs_auth;
 239  239  
 240  240          /* Prevent the nfsauth_refresh_thread from getting new work */
 241  241          mutex_enter(&nag->refreshq_lock);
 242  242          if (nag->refreshq_thread_state == REFRESHQ_THREAD_RUNNING) {
 243  243                  nag->refreshq_thread_state = REFRESHQ_THREAD_FINI_REQ;
 244  244                  cv_broadcast(&nag->refreshq_cv);
 245  245  
 246  246                  /* Wait for nfsauth_refresh_thread() to exit */
 247  247                  while (nag->refreshq_thread_state != REFRESHQ_THREAD_HALTED)
 248  248                          cv_wait(&nag->refreshq_cv, &nag->refreshq_lock);
↓ open down ↓ 14 lines elided ↑ open up ↑
 263  263                          strfree(ran->ran_netid);
 264  264                          kmem_free(ran, sizeof (*ran));
 265  265                  }
 266  266  
 267  267                  list_destroy(&ren->ren_authlist);
 268  268                  exi_rele(ren->ren_exi);
 269  269                  kmem_free(ren, sizeof (*ren));
 270  270          }
 271  271  }
 272  272  
 273      -/*ARGSUSED*/
 274      -static void
 275      -nfsauth_zone_fini(zoneid_t zoneid, void *data)
      273 +void
      274 +nfsauth_zone_fini(nfs_globals_t *ng)
 276  275  {
 277      -        nfsauth_globals_t *nag = data;
      276 +        nfsauth_globals_t *nag = ng->nfs_auth;
 278  277  
      278 +        ng->nfs_auth = NULL;
      279 +
 279  280          list_destroy(&nag->refreshq_queue);
 280  281          cv_destroy(&nag->refreshq_cv);
 281  282          mutex_destroy(&nag->refreshq_lock);
 282  283          mutex_destroy(&nag->mountd_lock);
 283  284          /* Extra cleanup. */
 284  285          if (nag->mountd_dh != NULL)
 285  286                  door_ki_rele(nag->mountd_dh);
 286  287          kmem_free(nag, sizeof (*nag));
 287  288  }
 288  289  
↓ open down ↓ 582 lines elided ↑ open up ↑
 871  872          uid_t                   tmpuid;
 872  873          gid_t                   tmpgid;
 873  874          uint_t                  tmpngids;
 874  875          gid_t                   *tmpgids;
 875  876  
 876  877          avl_index_t             where;  /* used for avl_find()/avl_insert() */
 877  878  
 878  879          ASSERT(cr != NULL);
 879  880  
 880  881          ASSERT3P(curzone, ==, exi->exi_zone);
 881      -        nag = zone_getspecific(nfsauth_zone_key, curzone);
      882 +        nag = nfsauth_get_zg();
 882  883  
 883  884          /*
 884  885           * Now check whether this client already
 885  886           * has an entry for this flavor in the cache
 886  887           * for this export.
 887  888           * Get the caller's address, mask off the
 888  889           * parts of the address that do not identify
 889  890           * the host (port number, etc), and then hash
 890  891           * it to find the chain of cache entries.
 891  892           */
↓ open down ↓ 556 lines elided ↑ open up ↑
1448 1449                  avl_tree_t *tree = exi->exi_cache[i];
1449 1450                  void *cookie = NULL;
1450 1451                  struct auth_cache_clnt *node;
1451 1452  
1452 1453                  while ((node = avl_destroy_nodes(tree, &cookie)) != NULL)
1453 1454                          nfsauth_free_clnt_node(node);
1454 1455          }
1455 1456  }
1456 1457  
1457 1458  /*
1458      - * Called by the kernel memory allocator when
1459      - * memory is low. Free unused cache entries.
1460      - * If that's not enough, the VM system will
1461      - * call again for some more.
     1459 + * Called by the kernel memory allocator when memory is low.
     1460 + * Free unused cache entries. If that's not enough, the VM system
     1461 + * will call again for some more.
     1462 + *
     1463 + * This needs to operate on all zones, so we take a reader lock
     1464 + * on the list of zones and walk the list.  This is OK here
     1465 + * becuase exi_cache_trim doesn't block or cause new objects
     1466 + * to be allocated (basically just frees lots of stuff).
     1467 + * Use care if nfssrv_globals_rwl is taken as reader in any
     1468 + * other cases because it will block nfs_server_zone_init
     1469 + * and nfs_server_zone_fini, which enter as writer.
1462 1470   */
1463 1471  /*ARGSUSED*/
1464 1472  void
1465 1473  exi_cache_reclaim(void *cdrarg)
1466 1474  {
     1475 +        nfs_globals_t *ng;
     1476 +
     1477 +        rw_enter(&nfssrv_globals_rwl, RW_READER);
     1478 +
     1479 +        ng = list_head(&nfssrv_globals_list);
     1480 +        while (ng != NULL) {
     1481 +                exi_cache_reclaim_zone(ng);
     1482 +                ng = list_next(&nfssrv_globals_list, ng);
     1483 +        }
     1484 +
     1485 +        rw_exit(&nfssrv_globals_rwl);
     1486 +}
     1487 +
     1488 +static void
     1489 +exi_cache_reclaim_zone(nfs_globals_t *ng)
     1490 +{
1467 1491          int i;
1468 1492          struct exportinfo *exi;
1469      -        nfs_export_t *ne = nfs_get_export();
     1493 +        nfs_export_t *ne = ng->nfs_export;
1470 1494  
1471 1495          rw_enter(&ne->exported_lock, RW_READER);
1472 1496  
1473 1497          for (i = 0; i < EXPTABLESIZE; i++) {
1474 1498                  for (exi = ne->exptable[i]; exi; exi = exi->fid_hash.next)
1475 1499                          exi_cache_trim(exi);
1476 1500          }
1477 1501  
1478 1502          rw_exit(&ne->exported_lock);
1479 1503  
1480 1504          atomic_inc_uint(&nfsauth_cache_reclaim);
1481 1505  }
1482 1506  
1483      -void
     1507 +static void
1484 1508  exi_cache_trim(struct exportinfo *exi)
1485 1509  {
1486 1510          struct auth_cache_clnt *c;
1487 1511          struct auth_cache_clnt *nextc;
1488 1512          struct auth_cache *p;
1489 1513          struct auth_cache *next;
1490 1514          int i;
1491 1515          time_t stale_time;
1492 1516          avl_tree_t *tree;
1493 1517  
↓ open down ↓ 83 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX