Print this page
11083 support NFS server in zone
Portions contributed by: Dan Kruchinin <dan.kruchinin@nexenta.com>
Portions contributed by: Stepan Zastupov <stepan.zastupov@gmail.com>
Portions contributed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Portions contributed by: Mike Zeller <mike@mikezeller.net>
Portions contributed by: Dan McDonald <danmcd@joyent.com>
Portions contributed by: Gordon Ross <gordon.w.ross@gmail.com>
Portions contributed by: Vitaliy Gusev <gusev.vitaliy@gmail.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Jason King <jbk@joyent.com>
Reviewed by: C Fraire <cfraire@me.com>
Change-Id: I22f289d357503f9b48a0bc2482cc4328a6d43d16

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/sharefs/sharetab.c
          +++ new/usr/src/uts/common/fs/sharefs/sharetab.c
↓ open down ↓ 15 lines elided ↑ open up ↑
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  24   24   */
  25   25  
       26 +/*
       27 + * Copyright 2018 Nexenta Systems, Inc.
       28 + * Copyright 2020 Joyent, Inc.
       29 + */
       30 +
  26   31  #include <sys/types.h>
  27   32  #include <sys/types32.h>
  28   33  #include <sys/param.h>
  29   34  #include <sys/systm.h>
  30   35  #include <rpc/types.h>
  31   36  #include <sys/vfs.h>
  32   37  #include <sys/siginfo.h>
  33   38  #include <sys/proc.h>           /* for exit() declaration */
  34   39  #include <sys/kmem.h>
  35   40  #include <sys/pathname.h>
↓ open down ↓ 4 lines elided ↑ open up ↑
  40   45  #include <sys/policy.h>
  41   46  
  42   47  #include <sharefs/sharefs.h>
  43   48  
  44   49  /*
  45   50   * A macro to avoid cut-and-paste errors on getting a string field
  46   51   * from user-land.
  47   52   */
  48   53  #define SHARETAB_COPYIN(field)                                          \
  49   54          if (copyinstr(STRUCT_FGETP(u_sh, sh_##field),                   \
  50      -                        buf,                                            \
  51      -                        bufsz + 1,      /* Add one for extra NUL */     \
  52      -                        &len)) {                                        \
       55 +            buf,                                                        \
       56 +            bufsz + 1,  /* Add one for extra NUL */                     \
       57 +            &len)) {                                                    \
  53   58                  error = EFAULT;                                         \
  54   59                  goto cleanup;                                           \
  55   60          }                                                               \
  56      -        /*                                                              \
  57      -         * Need to remove 1 because copyinstr() counts the NUL.         \
  58      -         */                                                             \
       61 +        /* Need to remove 1 because copyinstr() counts the NUL */       \
  59   62          len--;                                                          \
  60   63          sh->sh_##field = kmem_alloc(len + 1, KM_SLEEP);                 \
  61   64          bcopy(buf, sh->sh_##field, len);                                \
  62   65          sh->sh_##field[len] = '\0';                                     \
  63   66          shl.shl_##field = (int)len;                                     \
  64   67          sh->sh_size += shl.shl_##field; /* Debug counting */
  65   68  
  66   69  #define SHARETAB_DELETE_FIELD(field)                                    \
  67      -        if (sh->sh_##field) {                                           \
       70 +        if (sh->sh_##field != NULL) {                                   \
  68   71                  kmem_free(sh->sh_##field,                               \
  69      -                        shl ? shl->shl_##field + 1 :                    \
  70      -                        strlen(sh->sh_##field) + 1);                    \
       72 +                    shl ? shl->shl_##field + 1 :                        \
       73 +                    strlen(sh->sh_##field) + 1);                        \
  71   74          }
  72   75  
  73      -sharetab_t      *sharefs_sharetab = NULL;       /* The incore sharetab. */
  74      -size_t          sharetab_size;
  75      -uint_t          sharetab_count;
       76 +static zone_key_t sharetab_zone_key;
  76   77  
  77      -krwlock_t       sharetab_lock;  /* lock to protect the cached sharetab */
  78      -
  79      -krwlock_t       sharefs_lock;   /* lock to protect the vnode ops */
  80      -
  81      -timestruc_t     sharetab_mtime;
  82      -timestruc_t     sharetab_snap_time;
  83      -
  84      -uint_t          sharetab_generation;    /* Only increments and wraps! */
  85      -
  86   78  /*
  87   79   * Take care of cleaning up a share.
  88   80   * If passed in a length array, use it to determine how much
  89   81   * space to clean up. Else, figure that out.
  90   82   */
  91   83  static void
  92   84  sharefree(share_t *sh, sharefs_lens_t *shl)
  93   85  {
  94      -        if (!sh)
       86 +        if (sh == NULL)
  95   87                  return;
  96   88  
  97   89          SHARETAB_DELETE_FIELD(path);
  98   90          SHARETAB_DELETE_FIELD(res);
  99   91          SHARETAB_DELETE_FIELD(fstype);
 100   92          SHARETAB_DELETE_FIELD(opts);
 101   93          SHARETAB_DELETE_FIELD(descr);
 102   94  
 103      -        kmem_free(sh, sizeof (share_t));
       95 +        kmem_free(sh, sizeof (*sh));
 104   96  }
 105   97  
 106   98  /*
 107   99   * If there is no error, then this function is responsible for
 108  100   * cleaning up the memory associated with the share argument.
 109  101   */
 110  102  static int
 111      -sharefs_remove(share_t *sh, sharefs_lens_t *shl)
      103 +sharefs_remove(sharetab_globals_t *sg, share_t *sh, sharefs_lens_t *shl)
 112  104  {
 113  105          int             iHash;
 114  106          sharetab_t      *sht;
 115  107          share_t         *s, *p;
 116  108          int             iPath;
 117  109  
 118  110          if (!sh)
 119  111                  return (ENOENT);
 120  112  
 121      -        rw_enter(&sharetab_lock, RW_WRITER);
 122      -        for (sht = sharefs_sharetab; sht != NULL; sht = sht->s_next) {
 123      -                if (strcmp(sh->sh_fstype, sht->s_fstype) == 0) {
      113 +        rw_enter(&sg->sharetab_lock, RW_WRITER);
      114 +        for (sht = sg->sharefs_sharetab; sht != NULL; sht = sht->s_next) {
      115 +                if (strcmp(sh->sh_fstype, sht->s_fstype) == 0)
 124  116                          break;
 125      -                }
 126  117          }
 127  118  
 128  119          /*
 129  120           * There does not exist a fstype in memory which
 130  121           * matches the share passed in.
 131  122           */
 132      -        if (!sht) {
 133      -                rw_exit(&sharetab_lock);
      123 +        if (sht == NULL) {
      124 +                rw_exit(&sg->sharetab_lock);
 134  125                  return (ENOENT);
 135  126          }
 136  127  
 137      -        iPath = shl ? shl->shl_path : strlen(sh->sh_path);
      128 +        iPath = shl != NULL ? shl->shl_path : strlen(sh->sh_path);
 138  129          iHash = pkp_tab_hash(sh->sh_path, strlen(sh->sh_path));
 139  130  
 140  131          /*
 141  132           * Now walk down the hash table and find the entry to free!
 142  133           */
 143  134          for (p = NULL, s = sht->s_buckets[iHash].ssh_sh;
 144  135              s != NULL; s = s->sh_next) {
 145  136                  /*
 146  137                   * We need exact matches.
 147  138                   */
 148  139                  if (strcmp(sh->sh_path, s->sh_path) == 0 &&
 149  140                      strlen(s->sh_path) == iPath) {
 150      -                        if (p) {
      141 +                        if (p != NULL)
 151  142                                  p->sh_next = s->sh_next;
 152      -                        } else {
      143 +                        else
 153  144                                  sht->s_buckets[iHash].ssh_sh = s->sh_next;
 154      -                        }
 155  145  
 156  146                          ASSERT(sht->s_buckets[iHash].ssh_count != 0);
 157  147                          atomic_dec_32(&sht->s_buckets[iHash].ssh_count);
 158  148                          atomic_dec_32(&sht->s_count);
 159      -                        atomic_dec_32(&sharetab_count);
      149 +                        atomic_dec_32(&sg->sharetab_count);
 160  150  
 161      -                        ASSERT(sharetab_size >= s->sh_size);
 162      -                        sharetab_size -= s->sh_size;
      151 +                        ASSERT(sg->sharetab_size >= s->sh_size);
      152 +                        sg->sharetab_size -= s->sh_size;
 163  153  
 164      -                        gethrestime(&sharetab_mtime);
 165      -                        atomic_inc_32(&sharetab_generation);
      154 +                        gethrestime(&sg->sharetab_mtime);
      155 +                        atomic_inc_32(&sg->sharetab_generation);
 166  156  
 167  157                          break;
 168  158                  }
 169  159  
 170  160                  p = s;
 171  161          }
 172  162  
 173      -        rw_exit(&sharetab_lock);
      163 +        rw_exit(&sg->sharetab_lock);
 174  164  
 175      -        if (!s) {
      165 +        if (s == NULL)
 176  166                  return (ENOENT);
 177      -        }
 178  167  
 179  168          s->sh_next = NULL;
 180  169          sharefree(s, NULL);
 181  170  
 182      -        /*
 183      -         * We need to free the share for the caller.
 184      -         */
      171 +        /* We need to free the share for the caller */
 185  172          sharefree(sh, shl);
 186  173  
 187  174          return (0);
 188  175  }
 189  176  
 190  177  /*
 191  178   * The caller must have allocated memory for us to use.
 192  179   */
 193  180  static int
 194      -sharefs_add(share_t *sh, sharefs_lens_t *shl)
      181 +sharefs_add(sharetab_globals_t *sg, share_t *sh, sharefs_lens_t *shl)
 195  182  {
 196  183          int             iHash;
 197  184          sharetab_t      *sht;
 198  185          share_t         *s, *p;
 199  186          int             iPath;
 200  187          int             n;
 201  188  
 202      -        if (!sh) {
      189 +        if (sh == NULL)
 203  190                  return (ENOENT);
 204      -        }
 205  191  
 206      -        /*
 207      -         * We need to find the hash buckets for the fstype.
 208      -         */
 209      -        rw_enter(&sharetab_lock, RW_WRITER);
 210      -        for (sht = sharefs_sharetab; sht != NULL; sht = sht->s_next) {
 211      -                if (strcmp(sh->sh_fstype, sht->s_fstype) == 0) {
      192 +        /* We need to find the hash buckets for the fstype */
      193 +        rw_enter(&sg->sharetab_lock, RW_WRITER);
      194 +        for (sht = sg->sharefs_sharetab; sht != NULL; sht = sht->s_next) {
      195 +                if (strcmp(sh->sh_fstype, sht->s_fstype) == 0)
 212  196                          break;
 213      -                }
 214  197          }
 215  198  
 216      -        /*
 217      -         * Did not exist, so allocate one and add it to the
 218      -         * sharetab.
 219      -         */
 220      -        if (!sht) {
      199 +        /* Did not exist, so allocate one and add it to the sharetab */
      200 +        if (sht == NULL) {
 221  201                  sht = kmem_zalloc(sizeof (*sht), KM_SLEEP);
 222  202                  n = strlen(sh->sh_fstype);
 223  203                  sht->s_fstype = kmem_zalloc(n + 1, KM_SLEEP);
 224  204                  (void) strncpy(sht->s_fstype, sh->sh_fstype, n);
 225  205  
 226      -                sht->s_next = sharefs_sharetab;
 227      -                sharefs_sharetab = sht;
      206 +                sht->s_next = sg->sharefs_sharetab;
      207 +                sg->sharefs_sharetab = sht;
 228  208          }
 229  209  
 230      -        /*
 231      -         * Now we need to find where we have to add the entry.
 232      -         */
      210 +        /* Now we need to find where we have to add the entry */
      211 +        iPath = shl != NULL ? shl->shl_path : strlen(sh->sh_path);
 233  212          iHash = pkp_tab_hash(sh->sh_path, strlen(sh->sh_path));
 234  213  
 235      -        iPath = shl ? shl->shl_path : strlen(sh->sh_path);
 236      -
 237  214          if (shl) {
 238  215                  sh->sh_size = shl->shl_path + shl->shl_res +
 239  216                      shl->shl_fstype + shl->shl_opts + shl->shl_descr;
 240  217          } else {
 241  218                  sh->sh_size = strlen(sh->sh_path) +
 242  219                      strlen(sh->sh_res) + strlen(sh->sh_fstype) +
 243  220                      strlen(sh->sh_opts) + strlen(sh->sh_descr);
 244  221          }
 245  222  
 246      -        /*
 247      -         * We need to account for field seperators and
 248      -         * the EOL.
 249      -         */
      223 +        /* We need to account for field separators and the EOL */
 250  224          sh->sh_size += 5;
 251  225  
 252      -        /*
 253      -         * Now walk down the hash table and add the new entry!
 254      -         */
      226 +        /* Now walk down the hash table and add the new entry */
 255  227          for (p = NULL, s = sht->s_buckets[iHash].ssh_sh;
 256  228              s != NULL; s = s->sh_next) {
 257  229                  /*
 258  230                   * We need exact matches.
 259  231                   *
 260  232                   * We found a matching path. Either we have a
 261  233                   * duplicate path in a share command or we are
 262  234                   * being asked to replace an existing entry.
 263  235                   */
 264  236                  if (strcmp(sh->sh_path, s->sh_path) == 0 &&
 265  237                      strlen(s->sh_path) == iPath) {
 266      -                        if (p) {
      238 +                        if (p != NULL)
 267  239                                  p->sh_next = sh;
 268      -                        } else {
      240 +                        else
 269  241                                  sht->s_buckets[iHash].ssh_sh = sh;
 270      -                        }
 271  242  
 272  243                          sh->sh_next = s->sh_next;
 273  244  
 274      -                        ASSERT(sharetab_size >= s->sh_size);
 275      -                        sharetab_size -= s->sh_size;
 276      -                        sharetab_size += sh->sh_size;
      245 +                        ASSERT(sg->sharetab_size >= s->sh_size);
      246 +                        sg->sharetab_size -= s->sh_size;
      247 +                        sg->sharetab_size += sh->sh_size;
 277  248  
 278      -                        /*
 279      -                         * Get rid of the old node.
 280      -                         */
      249 +                        /* Get rid of the old node */
 281  250                          sharefree(s, NULL);
 282  251  
 283      -                        gethrestime(&sharetab_mtime);
 284      -                        atomic_inc_32(&sharetab_generation);
      252 +                        gethrestime(&sg->sharetab_mtime);
      253 +                        atomic_inc_32(&sg->sharetab_generation);
 285  254  
 286  255                          ASSERT(sht->s_buckets[iHash].ssh_count != 0);
 287      -                        rw_exit(&sharetab_lock);
      256 +                        rw_exit(&sg->sharetab_lock);
 288  257  
 289  258                          return (0);
 290  259                  }
 291  260  
 292  261                  p = s;
 293  262          }
 294  263  
 295  264          /*
 296  265           * Okay, we have gone through the entire hash chain and not
 297  266           * found a match. We just need to add this node.
 298  267           */
 299  268          sh->sh_next = sht->s_buckets[iHash].ssh_sh;
 300  269          sht->s_buckets[iHash].ssh_sh = sh;
 301  270          atomic_inc_32(&sht->s_buckets[iHash].ssh_count);
 302  271          atomic_inc_32(&sht->s_count);
 303      -        atomic_inc_32(&sharetab_count);
 304      -        sharetab_size += sh->sh_size;
      272 +        atomic_inc_32(&sg->sharetab_count);
      273 +        sg->sharetab_size += sh->sh_size;
 305  274  
 306      -        gethrestime(&sharetab_mtime);
 307      -        atomic_inc_32(&sharetab_generation);
      275 +        gethrestime(&sg->sharetab_mtime);
      276 +        atomic_inc_32(&sg->sharetab_generation);
 308  277  
 309      -        rw_exit(&sharetab_lock);
      278 +        rw_exit(&sg->sharetab_lock);
 310  279  
 311  280          return (0);
 312  281  }
 313  282  
      283 +/* ARGSUSED */
      284 +static void *
      285 +sharetab_zone_init(zoneid_t zoneid)
      286 +{
      287 +        sharetab_globals_t *sg;
      288 +
      289 +        sg = kmem_zalloc(sizeof (*sg), KM_SLEEP);
      290 +
      291 +        rw_init(&sg->sharetab_lock, NULL, RW_DEFAULT, NULL);
      292 +        rw_init(&sg->sharefs_lock, NULL, RW_DEFAULT, NULL);
      293 +
      294 +        sg->sharetab_size = 0;
      295 +        sg->sharetab_count = 0;
      296 +        sg->sharetab_generation = 1;
      297 +
      298 +        gethrestime(&sg->sharetab_mtime);
      299 +        gethrestime(&sg->sharetab_snap_time);
      300 +
      301 +        return (sg);
      302 +}
      303 +
      304 +/* ARGSUSED */
      305 +static void
      306 +sharetab_zone_fini(zoneid_t zoneid, void *data)
      307 +{
      308 +        sharetab_globals_t *sg = data;
      309 +
      310 +        rw_destroy(&sg->sharefs_lock);
      311 +        rw_destroy(&sg->sharetab_lock);
      312 +
      313 +        /* ALL of the allocated things must be cleaned before we free sg. */
      314 +        while (sg->sharefs_sharetab != NULL) {
      315 +                int i;
      316 +                sharetab_t *freeing = sg->sharefs_sharetab;
      317 +
      318 +                sg->sharefs_sharetab = freeing->s_next;
      319 +                kmem_free(freeing->s_fstype, strlen(freeing->s_fstype) + 1);
      320 +                for (i = 0; i < PKP_HASH_SIZE; i++) {
      321 +                        sharefs_hash_head_t *bucket;
      322 +
      323 +                        bucket = &(freeing->s_buckets[i]);
      324 +                        while (bucket->ssh_sh != NULL) {
      325 +                                share_t *share = bucket->ssh_sh;
      326 +
      327 +                                bucket->ssh_sh = share->sh_next;
      328 +                                sharefree(share, NULL);
      329 +                        }
      330 +                }
      331 +                kmem_free(freeing, sizeof (*freeing));
      332 +        }
      333 +
      334 +        kmem_free(sg, sizeof (*sg));
      335 +}
      336 +
 314  337  void
 315  338  sharefs_sharetab_init(void)
 316  339  {
 317      -        rw_init(&sharetab_lock, NULL, RW_DEFAULT, NULL);
 318      -        rw_init(&sharefs_lock, NULL, RW_DEFAULT, NULL);
      340 +        zone_key_create(&sharetab_zone_key, sharetab_zone_init,
      341 +            NULL, sharetab_zone_fini);
      342 +}
 319  343  
 320      -        sharetab_size = 0;
 321      -        sharetab_count = 0;
 322      -        sharetab_generation = 1;
 323      -
 324      -        gethrestime(&sharetab_mtime);
 325      -        gethrestime(&sharetab_snap_time);
      344 +sharetab_globals_t *
      345 +sharetab_get_globals(zone_t *zone)
      346 +{
      347 +        return (zone_getspecific(sharetab_zone_key, zone));
 326  348  }
 327  349  
 328  350  int
 329  351  sharefs_impl(enum sharefs_sys_op opcode, share_t *sh_in, uint32_t iMaxLen)
 330  352  {
 331  353          int             error = 0;
 332  354          size_t          len;
 333  355          size_t          bufsz;
 334  356          share_t         *sh;
 335      -
 336  357          sharefs_lens_t  shl;
 337      -
 338  358          model_t         model;
 339      -
 340  359          char            *buf = NULL;
      360 +        sharetab_globals_t *sg = sharetab_get_globals(curzone);
 341  361  
 342  362          STRUCT_DECL(share, u_sh);
 343  363  
 344  364          bufsz = iMaxLen;
 345  365  
 346  366          /*
 347  367           * Before we do anything, lets make sure we have
 348  368           * a sharetab in memory if we need one.
 349  369           */
 350      -        rw_enter(&sharetab_lock, RW_READER);
      370 +        rw_enter(&sg->sharetab_lock, RW_READER);
 351  371          switch (opcode) {
 352      -        case (SHAREFS_REMOVE) :
 353      -        case (SHAREFS_REPLACE) :
 354      -                if (!sharefs_sharetab) {
 355      -                        rw_exit(&sharetab_lock);
      372 +        case SHAREFS_REMOVE:
      373 +        case SHAREFS_REPLACE:
      374 +                if (!sg->sharefs_sharetab) {
      375 +                        rw_exit(&sg->sharetab_lock);
 356  376                          return (set_errno(ENOENT));
 357  377                  }
 358  378                  break;
 359      -        case (SHAREFS_ADD) :
 360      -        default :
      379 +        case SHAREFS_ADD:
      380 +        default:
 361  381                  break;
 362  382          }
 363      -        rw_exit(&sharetab_lock);
      383 +        rw_exit(&sg->sharetab_lock);
 364  384  
 365  385          model = get_udatamodel();
 366  386  
 367  387          /*
 368  388           * Initialize the data pointers.
 369  389           */
 370  390          STRUCT_INIT(u_sh, model);
 371      -        if (copyin(sh_in, STRUCT_BUF(u_sh), STRUCT_SIZE(u_sh))) {
      391 +        if (copyin(sh_in, STRUCT_BUF(u_sh), STRUCT_SIZE(u_sh)))
 372  392                  return (set_errno(EFAULT));
 373      -        }
 374  393  
 375      -        /*
 376      -         * Get the share.
 377      -         */
      394 +        /* Get the share */
 378  395          sh = kmem_zalloc(sizeof (share_t), KM_SLEEP);
 379  396  
 380      -        /*
 381      -         * Get some storage for copying in the strings.
 382      -         */
      397 +        /* Get some storage for copying in the strings */
 383  398          buf = kmem_zalloc(bufsz + 1, KM_SLEEP);
 384  399          bzero(&shl, sizeof (sharefs_lens_t));
 385  400  
 386      -        /*
 387      -         * Only grab these two until we know what we want.
 388      -         */
      401 +        /* Only grab these two until we know what we want */
 389  402          SHARETAB_COPYIN(path);
 390  403          SHARETAB_COPYIN(fstype);
 391  404  
 392  405          switch (opcode) {
 393      -        case (SHAREFS_ADD) :
 394      -        case (SHAREFS_REPLACE) :
      406 +        case SHAREFS_ADD:
      407 +        case SHAREFS_REPLACE:
 395  408                  SHARETAB_COPYIN(res);
 396  409                  SHARETAB_COPYIN(opts);
 397  410                  SHARETAB_COPYIN(descr);
 398      -
 399      -                error = sharefs_add(sh, &shl);
      411 +                error = sharefs_add(sg, sh, &shl);
 400  412                  break;
 401      -
 402      -        case (SHAREFS_REMOVE) :
 403      -
 404      -                error = sharefs_remove(sh, &shl);
      413 +        case SHAREFS_REMOVE:
      414 +                error = sharefs_remove(sg, sh, &shl);
 405  415                  break;
 406      -
 407  416          default:
 408  417                  error = EINVAL;
 409  418                  break;
 410  419          }
 411  420  
 412  421  cleanup:
 413      -
 414  422          /*
 415  423           * If there is no error, then we have stashed the structure
 416  424           * away in the sharetab hash table or have deleted it.
 417  425           *
 418  426           * Either way, the only reason to blow away the data is if
 419  427           * there was an error.
 420  428           */
 421      -        if (error != 0) {
      429 +        if (error != 0)
 422  430                  sharefree(sh, &shl);
 423      -        }
 424  431  
 425      -        if (buf) {
      432 +        if (buf != NULL)
 426  433                  kmem_free(buf, bufsz + 1);
 427      -        }
 428  434  
 429      -        return ((error != 0) ? set_errno(error) : 0);
      435 +        return (error != 0 ? set_errno(error) : 0);
 430  436  }
 431  437  
 432  438  int
 433  439  sharefs(enum sharefs_sys_op opcode, share_t *sh_in, uint32_t iMaxLen)
 434  440  {
 435      -        if (secpolicy_sys_config(CRED(), B_FALSE) != 0)
 436      -                return (set_errno(EPERM));
      441 +        /*
      442 +         * If we're in the global zone PRIV_SYS_CONFIG gives us the
      443 +         * privileges needed to act on sharetab. However if we're in
      444 +         * a non-global zone PRIV_SYS_CONFIG is not allowed. To work
      445 +         * around this issue PRIV_SYS_NFS is used in this case.
      446 +         *
      447 +         * TODO: This basically overloads the definition/use of
      448 +         * PRIV_SYS_NFS to work around the limitation of PRIV_SYS_CONFIG
      449 +         * in a zone. Solaris 11 solved this by implementing a PRIV_SYS_SHARE
      450 +         * we should do the same and replace the use of PRIV_SYS_NFS here and
      451 +         * in zfs_secpolicy_share.
      452 +         */
      453 +        if (INGLOBALZONE(curproc)) {
      454 +                if (secpolicy_sys_config(CRED(), B_FALSE) != 0)
      455 +                        return (set_errno(EPERM));
      456 +        } else {
      457 +                /* behave like zfs_secpolicy_share() */
      458 +                if (secpolicy_nfs(CRED()) != 0)
      459 +                        return (set_errno(EPERM));
 437  460  
      461 +        }
 438  462          return (sharefs_impl(opcode, sh_in, iMaxLen));
 439  463  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX