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/sharefs_vnops.c
          +++ new/usr/src/uts/common/fs/sharefs/sharefs_vnops.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  
    | 
      ↓ open down ↓ | 
    16 lines elided | 
    
      ↑ open up ↑ | 
  
  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 2007 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
  25   25   */
  26   26  
       27 +/*
       28 + * Copyright 2018 Nexenta Systems, Inc.
       29 + */
       30 +
  27   31  #include <fs/fs_subr.h>
  28   32  
  29   33  #include <sys/errno.h>
  30   34  #include <sys/file.h>
  31   35  #include <sys/kmem.h>
  32   36  #include <sys/kobj.h>
  33   37  #include <sys/cmn_err.h>
  34   38  #include <sys/stat.h>
  35   39  #include <sys/systm.h>
  36   40  #include <sys/sysmacros.h>
  37   41  #include <sys/atomic.h>
  
    | 
      ↓ open down ↓ | 
    1 lines elided | 
    
      ↑ open up ↑ | 
  
  38   42  #include <sys/vfs.h>
  39   43  #include <sys/vfs_opreg.h>
  40   44  
  41   45  #include <sharefs/sharefs.h>
  42   46  
  43   47  /*
  44   48   * sharefs_snap_create: create a large character buffer with
  45   49   * the shares enumerated.
  46   50   */
  47   51  static int
  48      -sharefs_snap_create(shnode_t *sft)
       52 +sharefs_snap_create(sharetab_globals_t *sg, shnode_t *sft)
  49   53  {
  50   54          sharetab_t              *sht;
  51   55          share_t                 *sh;
  52   56          size_t                  sWritten = 0;
  53   57          int                     iCount = 0;
  54   58          char                    *buf;
  55   59  
  56      -        rw_enter(&sharefs_lock, RW_WRITER);
  57      -        rw_enter(&sharetab_lock, RW_READER);
       60 +        rw_enter(&sg->sharefs_lock, RW_WRITER);
       61 +        rw_enter(&sg->sharetab_lock, RW_READER);
  58   62  
  59   63          if (sft->sharefs_snap) {
  60   64                  /*
  61   65                   * Nothing has changed, so no need to grab a new copy!
  62   66                   */
  63      -                if (sft->sharefs_generation == sharetab_generation) {
  64      -                        rw_exit(&sharetab_lock);
  65      -                        rw_exit(&sharefs_lock);
       67 +                if (sft->sharefs_generation == sg->sharetab_generation) {
       68 +                        rw_exit(&sg->sharetab_lock);
       69 +                        rw_exit(&sg->sharefs_lock);
  66   70                          return (0);
  67   71                  }
  68   72  
  69   73                  ASSERT(sft->sharefs_size != 0);
  70   74                  kmem_free(sft->sharefs_snap, sft->sharefs_size + 1);
  71   75                  sft->sharefs_snap = NULL;
  72   76          }
  73   77  
  74      -        sft->sharefs_size = sharetab_size;
  75      -        sft->sharefs_count = sharetab_count;
       78 +        sft->sharefs_size = sg->sharetab_size;
       79 +        sft->sharefs_count = sg->sharetab_count;
  76   80  
  77   81          if (sft->sharefs_size == 0) {
  78      -                rw_exit(&sharetab_lock);
  79      -                rw_exit(&sharefs_lock);
       82 +                rw_exit(&sg->sharetab_lock);
       83 +                rw_exit(&sg->sharefs_lock);
  80   84                  return (0);
  81   85          }
  82   86  
  83   87          sft->sharefs_snap = kmem_zalloc(sft->sharefs_size + 1, KM_SLEEP);
  84   88  
  85   89          buf = sft->sharefs_snap;
  86   90  
  87   91          /*
  88   92           * Walk the Sharetab, dumping each entry.
  89   93           */
  90      -        for (sht = sharefs_sharetab; sht != NULL; sht = sht->s_next) {
       94 +        for (sht = sg->sharefs_sharetab; sht != NULL; sht = sht->s_next) {
  91   95                  int     i;
  92   96  
  93   97                  for (i = 0; i < SHARETAB_HASHES; i++) {
  94   98                          for (sh = sht->s_buckets[i].ssh_sh;
  95   99                              sh != NULL;
  96  100                              sh = sh->sh_next) {
  97  101                                  int     n;
  98  102  
  99  103                                  if ((sWritten + sh->sh_size) >
 100  104                                      sft->sharefs_size) {
 101  105                                          goto error_fault;
 102  106                                  }
 103  107  
 104  108                                  /*
 105  109                                   * Note that sh->sh_size accounts
 106  110                                   * for the field seperators.
 107  111                                   * We need to add one for the EOL
 108  112                                   * marker. And we should note that
 109  113                                   * the space is accounted for in
 110  114                                   * each share by the EOS marker.
 111  115                                   */
 112  116                                  n = snprintf(&buf[sWritten],
 113  117                                      sh->sh_size + 1,
 114  118                                      "%s\t%s\t%s\t%s\t%s\n",
 115  119                                      sh->sh_path,
 116  120                                      sh->sh_res,
 117  121                                      sh->sh_fstype,
 118  122                                      sh->sh_opts,
 119  123                                      sh->sh_descr);
 120  124  
 121  125                                  if (n != sh->sh_size) {
 122  126                                          goto error_fault;
 123  127                                  }
 124  128  
  
    | 
      ↓ open down ↓ | 
    24 lines elided | 
    
      ↑ open up ↑ | 
  
 125  129                                  sWritten += n;
 126  130                                  iCount++;
 127  131                          }
 128  132                  }
 129  133          }
 130  134  
 131  135          /*
 132  136           * We want to record the generation number and
 133  137           * mtime inside this snapshot.
 134  138           */
 135      -        gethrestime(&sharetab_snap_time);
 136      -        sft->sharefs_snap_time = sharetab_snap_time;
 137      -        sft->sharefs_generation = sharetab_generation;
      139 +        gethrestime(&sg->sharetab_snap_time);
      140 +        sft->sharefs_snap_time = sg->sharetab_snap_time;
      141 +        sft->sharefs_generation = sg->sharetab_generation;
 138  142  
 139  143          ASSERT(iCount == sft->sharefs_count);
 140  144  
 141      -        rw_exit(&sharetab_lock);
 142      -        rw_exit(&sharefs_lock);
      145 +        rw_exit(&sg->sharetab_lock);
      146 +        rw_exit(&sg->sharefs_lock);
 143  147          return (0);
 144  148  
 145  149  error_fault:
 146  150  
 147  151          kmem_free(sft->sharefs_snap, sft->sharefs_size + 1);
 148  152          sft->sharefs_size = 0;
 149  153          sft->sharefs_count = 0;
 150  154          sft->sharefs_snap = NULL;
 151      -        rw_exit(&sharetab_lock);
 152      -        rw_exit(&sharefs_lock);
      155 +        rw_exit(&sg->sharetab_lock);
      156 +        rw_exit(&sg->sharefs_lock);
 153  157  
 154  158          return (EFAULT);
 155  159  }
 156  160  
 157  161  /* ARGSUSED */
 158  162  static int
 159  163  sharefs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
 160  164      caller_context_t *ct)
 161  165  {
 162  166          timestruc_t     now;
 163  167          shnode_t        *sft = VTOSH(vp);
      168 +        sharetab_globals_t *sg = sharetab_get_globals(vp->v_vfsp->vfs_zone);
 164  169  
 165  170          vap->va_type = VREG;
 166  171          vap->va_mode = S_IRUSR | S_IRGRP | S_IROTH;
 167  172          vap->va_nodeid = SHAREFS_INO_FILE;
 168  173          vap->va_nlink = 1;
 169  174  
 170      -        rw_enter(&sharefs_lock, RW_READER);
      175 +        rw_enter(&sg->sharefs_lock, RW_READER);
 171  176  
 172  177          /*
 173  178           * If we get asked about a snapped vnode, then
 174  179           * we must report the data in that vnode.
 175  180           *
 176  181           * Else we report what is currently in the
 177  182           * sharetab.
 178  183           */
 179  184          if (sft->sharefs_real_vp) {
 180      -                rw_enter(&sharetab_lock, RW_READER);
 181      -                vap->va_size = sharetab_size;
 182      -                vap->va_mtime = sharetab_mtime;
 183      -                rw_exit(&sharetab_lock);
      185 +                rw_enter(&sg->sharetab_lock, RW_READER);
      186 +                vap->va_size = sg->sharetab_size;
      187 +                vap->va_mtime = sg->sharetab_mtime;
      188 +                rw_exit(&sg->sharetab_lock);
 184  189          } else {
 185  190                  vap->va_size = sft->sharefs_size;
 186  191                  vap->va_mtime = sft->sharefs_snap_time;
 187  192          }
 188      -        rw_exit(&sharefs_lock);
      193 +        rw_exit(&sg->sharefs_lock);
 189  194  
 190  195          gethrestime(&now);
 191  196          vap->va_atime = vap->va_ctime = now;
 192  197  
 193  198          vap->va_uid = 0;
 194  199          vap->va_gid = 0;
 195  200          vap->va_rdev = 0;
 196  201          vap->va_blksize = DEV_BSIZE;
 197  202          vap->va_nblocks = howmany(vap->va_size, vap->va_blksize);
 198  203          vap->va_seq = 0;
 199  204          vap->va_fsid = vp->v_vfsp->vfs_dev;
 200  205  
 201  206          return (0);
 202  207  }
 203  208  
 204  209  /* ARGSUSED */
 205  210  static int
 206  211  sharefs_access(vnode_t *vp, int mode, int flags, cred_t *cr,
 207  212      caller_context_t *ct)
 208  213  {
 209  214          if (mode & (VWRITE|VEXEC))
 210  215                  return (EROFS);
 211  216  
 212  217          return (0);
 213  218  }
 214  219  
 215  220  /* ARGSUSED */
 216  221  int
 217  222  sharefs_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
 218  223  {
 219  224          vnode_t         *vp;
 220  225          vnode_t         *ovp = *vpp;
 221  226          shnode_t        *sft;
 222  227          int             error = 0;
 223  228  
 224  229          if (flag & FWRITE)
 225  230                  return (EINVAL);
 226  231  
 227  232          /*
 228  233           * Create a new sharefs vnode for each operation. In order to
 229  234           * avoid locks, we create a snapshot which can not change during
 230  235           * reads.
 231  236           */
 232  237          vp = gfs_file_create(sizeof (shnode_t), NULL, sharefs_ops_data);
 233  238  
 234  239          ((gfs_file_t *)vp->v_data)->gfs_ino = SHAREFS_INO_FILE;
 235  240  
 236  241          /*
 237  242           * Hold the parent!
 238  243           */
 239  244          VFS_HOLD(ovp->v_vfsp);
 240  245  
 241  246          VN_SET_VFS_TYPE_DEV(vp, ovp->v_vfsp, VREG, 0);
 242  247  
 243  248          vp->v_flag |= VROOT | VNOCACHE | VNOMAP | VNOSWAP | VNOMOUNT;
 244  249  
 245  250          *vpp = vp;
 246  251          VN_RELE(ovp);
 247  252  
 248  253          sft = VTOSH(vp);
 249  254  
 250  255          /*
 251  256           * No need for the lock, no other thread can be accessing
  
    | 
      ↓ open down ↓ | 
    53 lines elided | 
    
      ↑ open up ↑ | 
  
 252  257           * this data structure.
 253  258           */
 254  259          atomic_inc_32(&sft->sharefs_refs);
 255  260          sft->sharefs_real_vp = 0;
 256  261  
 257  262          /*
 258  263           * Since the sharetab could easily change on us whilst we
 259  264           * are dumping an extremely huge sharetab, we make a copy
 260  265           * of it here and use it to dump instead.
 261  266           */
 262      -        error = sharefs_snap_create(sft);
      267 +        error = sharefs_snap_create(sharetab_get_globals(vp->v_vfsp->vfs_zone),
      268 +            sft);
 263  269  
 264  270          return (error);
 265  271  }
 266  272  
 267  273  /* ARGSUSED */
 268  274  int
 269  275  sharefs_close(vnode_t *vp, int flag, int count,
 270  276      offset_t off, cred_t *cr, caller_context_t *ct)
 271  277  {
 272  278          shnode_t        *sft = VTOSH(vp);
      279 +        sharetab_globals_t *sg = sharetab_get_globals(vp->v_vfsp->vfs_zone);
 273  280  
 274  281          if (count > 1)
 275  282                  return (0);
 276  283  
 277      -        rw_enter(&sharefs_lock, RW_WRITER);
      284 +        rw_enter(&sg->sharefs_lock, RW_WRITER);
 278  285          if (vp->v_count == 1) {
 279  286                  if (sft->sharefs_snap != NULL) {
 280  287                          kmem_free(sft->sharefs_snap, sft->sharefs_size + 1);
 281  288                          sft->sharefs_size = 0;
 282  289                          sft->sharefs_snap = NULL;
 283  290                          sft->sharefs_generation = 0;
 284  291                  }
 285  292          }
 286  293          atomic_dec_32(&sft->sharefs_refs);
 287      -        rw_exit(&sharefs_lock);
      294 +        rw_exit(&sg->sharefs_lock);
 288  295  
 289  296          return (0);
 290  297  }
 291  298  
 292  299  /* ARGSUSED */
 293  300  static int
 294  301  sharefs_read(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr,
 295      -                        caller_context_t *ct)
      302 +    caller_context_t *ct)
 296  303  {
 297  304          shnode_t        *sft = VTOSH(vp);
 298  305          off_t           off = uio->uio_offset;
 299  306          size_t          len = uio->uio_resid;
 300  307          int             error = 0;
      308 +        sharetab_globals_t *sg = sharetab_get_globals(vp->v_vfsp->vfs_zone);
 301  309  
 302      -        rw_enter(&sharefs_lock, RW_READER);
      310 +        rw_enter(&sg->sharefs_lock, RW_READER);
 303  311  
 304  312          /*
 305  313           * First check to see if we need to grab a new snapshot.
 306  314           */
 307  315          if (off == (off_t)0) {
 308      -                rw_exit(&sharefs_lock);
 309      -                error = sharefs_snap_create(sft);
      316 +                rw_exit(&sg->sharefs_lock);
      317 +                error = sharefs_snap_create(sg, sft);
 310  318                  if (error) {
 311  319                          return (EFAULT);
 312  320                  }
 313      -                rw_enter(&sharefs_lock, RW_READER);
      321 +                rw_enter(&sg->sharefs_lock, RW_READER);
 314  322          }
 315  323  
 316  324          /* LINTED */
 317  325          if (len <= 0 || off >= sft->sharefs_size) {
 318      -                rw_exit(&sharefs_lock);
      326 +                rw_exit(&sg->sharefs_lock);
 319  327                  return (error);
 320  328          }
 321  329  
 322  330          if ((size_t)(off + len) > sft->sharefs_size)
 323  331                  len = sft->sharefs_size - off;
 324  332  
 325  333          if (off < 0 || len > sft->sharefs_size) {
 326      -                rw_exit(&sharefs_lock);
      334 +                rw_exit(&sg->sharefs_lock);
 327  335                  return (EFAULT);
 328  336          }
 329  337  
 330  338          if (len != 0) {
 331  339                  error = uiomove(sft->sharefs_snap + off,
 332  340                      len, UIO_READ, uio);
 333  341          }
 334  342  
 335      -        rw_exit(&sharefs_lock);
      343 +        rw_exit(&sg->sharefs_lock);
 336  344          return (error);
 337  345  }
 338  346  
 339  347  /* ARGSUSED */
 340  348  static void
 341  349  sharefs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *tx)
 342  350  {
 343  351          gfs_file_t      *fp = vp->v_data;
 344  352          shnode_t        *sft;
      353 +        sharetab_globals_t *sg = sharetab_get_globals(vp->v_vfsp->vfs_zone);
 345  354  
 346  355          sft = (shnode_t *)gfs_file_inactive(vp);
 347  356          if (sft) {
 348      -                rw_enter(&sharefs_lock, RW_WRITER);
      357 +                rw_enter(&sg->sharefs_lock, RW_WRITER);
 349  358                  if (sft->sharefs_snap != NULL) {
 350  359                          kmem_free(sft->sharefs_snap, sft->sharefs_size + 1);
 351  360                  }
 352  361  
 353  362                  kmem_free(sft, fp->gfs_size);
 354      -                rw_exit(&sharefs_lock);
      363 +                rw_exit(&sg->sharefs_lock);
 355  364          }
 356  365  }
 357  366  
 358  367  vnode_t *
 359  368  sharefs_create_root_file(vfs_t *vfsp)
 360  369  {
 361  370          vnode_t         *vp;
 362  371          shnode_t        *sft;
 363  372  
 364  373          vp = gfs_root_create_file(sizeof (shnode_t),
 365  374              vfsp, sharefs_ops_data, SHAREFS_INO_FILE);
 366  375  
 367  376          sft = VTOSH(vp);
 368  377  
 369  378          sft->sharefs_real_vp = 1;
 370  379  
 371  380          return (vp);
 372  381  }
 373  382  
 374  383  const fs_operation_def_t sharefs_tops_data[] = {
 375  384          { VOPNAME_OPEN,         { .vop_open = sharefs_open } },
 376  385          { VOPNAME_CLOSE,        { .vop_close = sharefs_close } },
 377  386          { VOPNAME_IOCTL,        { .error = fs_inval } },
 378  387          { VOPNAME_GETATTR,      { .vop_getattr = sharefs_getattr } },
 379  388          { VOPNAME_ACCESS,       { .vop_access = sharefs_access } },
 380  389          { VOPNAME_INACTIVE,     { .vop_inactive = sharefs_inactive } },
 381  390          { VOPNAME_READ,         { .vop_read = sharefs_read } },
 382  391          { VOPNAME_SEEK,         { .vop_seek = fs_seek } },
 383  392          { NULL }
 384  393  };
  
    | 
      ↓ open down ↓ | 
    20 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX