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/nfs/nfs_sys.c
          +++ new/usr/src/uts/common/fs/nfs/nfs_sys.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
  
    | 
      ↓ open down ↓ | 
    10 lines elided | 
    
      ↑ open up ↑ | 
  
  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
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
       21 +
  21   22  /*
  22   23   * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  23   24   * Use is subject to license terms.
  24      - *
       25 + */
       26 +
       27 +/*
  25   28   * Copyright (c) 1983,1984,1985,1986,1987,1988,1989  AT&T.
  26   29   * All rights reserved.
  27   30   */
  28   31  
       32 +/*
       33 + * Copyright 2018 Nexenta Systems, Inc.
       34 + */
       35 +
  29   36  #include <sys/types.h>
  30   37  #include <rpc/types.h>
  31   38  #include <sys/systm.h>
  32   39  #include <sys/vfs.h>
  33   40  #include <sys/errno.h>
  34   41  #include <sys/cred.h>
  35   42  #include <sys/policy.h>
  36   43  #include <sys/siginfo.h>
  37   44  #include <sys/proc.h>           /* for exit() declaration */
  38   45  #include <sys/kmem.h>
  39   46  #include <nfs/nfs4.h>
  40   47  #include <nfs/nfssys.h>
  41   48  #include <sys/thread.h>
  42   49  #include <rpc/auth.h>
  43   50  #include <rpc/rpcsys.h>
  44   51  #include <rpc/svc.h>
  45   52  
  46   53  /*
  47   54   * This is filled in with an appropriate address for the
  48   55   * function that will traverse the rfs4_client_t table
  49   56   * and mark any matching IP Address as "forced_expire".
  50   57   *
  51   58   * It is the server init() function that plops the
  52   59   * function pointer.
  53   60   */
  54   61  void (*rfs4_client_clrst)(struct nfs4clrst_args *) = NULL;
  55   62  
  56   63  /* This filled in by nfssrv:_init() */
  57   64  void (*nfs_srv_quiesce_func)(void) = NULL;
  58   65  
  59   66  extern void nfscmd_args(uint_t);
  60   67  
  61   68  /*
  62   69   * These will be reset by klmmod:lm_svc(), when lockd starts NLM service,
  63   70   * based on values read by lockd from /etc/default/nfs. Since nfssrv depends on
  64   71   * klmmod, the declarations need to be here (in nfs, on which both depend) so
  65   72   * that nfssrv can see the klmmod changes.
  66   73   * When the dependency of NFSv4 on NLM/lockd is removed, this will need to
  67   74   * be adjusted.
  68   75   */
  69   76  #define RFS4_LEASETIME 90                       /* seconds */
  70   77  time_t rfs4_lease_time = RFS4_LEASETIME;
  71   78  time_t rfs4_grace_period = RFS4_LEASETIME;
  72   79  
  
    | 
      ↓ open down ↓ | 
    34 lines elided | 
    
      ↑ open up ↑ | 
  
  73   80  /* DSS: distributed stable storage */
  74   81  size_t nfs4_dss_buflen = 0;
  75   82  /* This filled in by nfssrv:_init() */
  76   83  int (*nfs_srv_dss_func)(char *, size_t) = NULL;
  77   84  
  78   85  int
  79   86  nfs_export(void *arg)
  80   87  {
  81   88          STRUCT_DECL(exportfs_args, ea);
  82   89  
  83      -        if (!INGLOBALZONE(curproc))
  84      -                return (set_errno(EPERM));
  85   90          STRUCT_INIT(ea, get_udatamodel());
  86   91          if (copyin(arg, STRUCT_BUF(ea), STRUCT_SIZE(ea)))
  87   92                  return (set_errno(EFAULT));
  88   93  
  89   94          return (exportfs(STRUCT_BUF(ea), get_udatamodel(), CRED()));
  90   95  }
  91   96  
  92   97  int
  93   98  nfssys(enum nfssys_op opcode, void *arg)
  94   99  {
  95  100          int error = 0;
  96  101  
  97  102          if (!(opcode == NFS_REVAUTH || opcode == NFS4_SVC) &&
  98  103              secpolicy_nfs(CRED()) != 0)
  99  104                  return (set_errno(EPERM));
 100  105  
 101  106          switch (opcode) {
 102  107          case NFS4_CLR_STATE: { /* Clear NFS4 client state */
 103  108                  struct nfs4clrst_args clr;
  
    | 
      ↓ open down ↓ | 
    9 lines elided | 
    
      ↑ open up ↑ | 
  
 104  109                  STRUCT_DECL(nfs4clrst_args, u_clr);
 105  110  
 106  111                  /*
 107  112                   * If the server is not loaded then no point in
 108  113                   * clearing nothing :-)
 109  114                   */
 110  115                  if (rfs4_client_clrst == NULL) {
 111  116                          break;
 112  117                  }
 113  118  
 114      -                if (!INGLOBALZONE(curproc))
 115      -                        return (set_errno(EPERM));
 116      -
 117  119                  STRUCT_INIT(u_clr, get_udatamodel());
 118  120  
 119  121                  if (copyin(arg, STRUCT_BUF(u_clr), STRUCT_SIZE(u_clr)))
 120  122                          return (set_errno(EFAULT));
 121  123  
 122  124                  clr.vers = STRUCT_FGET(u_clr, vers);
 123  125  
 124  126                  if (clr.vers != NFS4_CLRST_VERSION)
 125  127                          return (set_errno(EINVAL));
 126  128  
 127  129                  clr.addr_type = STRUCT_FGET(u_clr, addr_type);
 128  130                  clr.ap = STRUCT_FGETP(u_clr, ap);
 129  131                  rfs4_client_clrst(&clr);
 130  132                  break;
 131  133          }
 132  134  
 133  135          case SVCPOOL_CREATE: { /* setup an RPC server thread pool */
 134  136                  struct svcpool_args p;
 135  137  
 136  138                  if (copyin(arg, &p, sizeof (p)))
 137  139                          return (set_errno(EFAULT));
 138  140  
 139  141                  error = svc_pool_create(&p);
 140  142                  break;
 141  143          }
 142  144  
 143  145          case SVCPOOL_WAIT: { /* wait in kernel for threads to be needed */
 144  146                  int id;
 145  147  
 146  148                  if (copyin(arg, &id, sizeof (id)))
 147  149                          return (set_errno(EFAULT));
 148  150  
 149  151                  error = svc_wait(id);
 150  152                  break;
 151  153          }
 152  154  
 153  155          case SVCPOOL_RUN: { /* give work to a runnable thread */
 154  156                  int id;
 155  157  
 156  158                  if (copyin(arg, &id, sizeof (id)))
  
    | 
      ↓ open down ↓ | 
    30 lines elided | 
    
      ↑ open up ↑ | 
  
 157  159                          return (set_errno(EFAULT));
 158  160  
 159  161                  error = svc_do_run(id);
 160  162                  break;
 161  163          }
 162  164  
 163  165          case RDMA_SVC_INIT: {
 164  166                  struct rdma_svc_args rsa;
 165  167                  char netstore[20] = "tcp";
 166  168  
 167      -                if (!INGLOBALZONE(curproc))
 168      -                        return (set_errno(EPERM));
 169  169                  if (get_udatamodel() != DATAMODEL_NATIVE) {
 170  170                          STRUCT_DECL(rdma_svc_args, ursa);
 171  171  
 172  172                          STRUCT_INIT(ursa, get_udatamodel());
 173  173                          if (copyin(arg, STRUCT_BUF(ursa), STRUCT_SIZE(ursa)))
 174  174                                  return (set_errno(EFAULT));
 175  175  
 176  176                          rsa.poolid = STRUCT_FGET(ursa, poolid);
 177  177                          rsa.nfs_versmin = STRUCT_FGET(ursa, nfs_versmin);
 178  178                          rsa.nfs_versmax = STRUCT_FGET(ursa, nfs_versmax);
 179  179                          rsa.delegation = STRUCT_FGET(ursa, delegation);
 180  180                  } else {
 181  181                          if (copyin(arg, &rsa, sizeof (rsa)))
  
    | 
      ↓ open down ↓ | 
    3 lines elided | 
    
      ↑ open up ↑ | 
  
 182  182                                  return (set_errno(EFAULT));
 183  183                  }
 184  184                  rsa.netid = netstore;
 185  185  
 186  186                  error = rdma_start(&rsa);
 187  187                  break;
 188  188          }
 189  189  
 190  190          case NFS_SVC: { /* NFS server daemon */
 191  191                  STRUCT_DECL(nfs_svc_args, nsa);
 192      -
 193      -                if (!INGLOBALZONE(curproc))
 194      -                        return (set_errno(EPERM));
 195  192                  STRUCT_INIT(nsa, get_udatamodel());
 196  193  
 197  194                  if (copyin(arg, STRUCT_BUF(nsa), STRUCT_SIZE(nsa)))
 198  195                          return (set_errno(EFAULT));
 199  196  
 200  197                  error = nfs_svc(STRUCT_BUF(nsa), get_udatamodel());
 201  198                  break;
 202  199          }
 203  200  
 204  201          case EXPORTFS: { /* export a file system */
 205  202                  error = nfs_export(arg);
 206  203                  break;
 207  204          }
 208  205  
 209  206          case NFS_GETFH: { /* get a file handle */
 210  207                  STRUCT_DECL(nfs_getfh_args, nga);
 211  208  
 212      -                if (!INGLOBALZONE(curproc))
 213      -                        return (set_errno(EPERM));
 214  209                  STRUCT_INIT(nga, get_udatamodel());
 215  210                  if (copyin(arg, STRUCT_BUF(nga), STRUCT_SIZE(nga)))
 216  211                          return (set_errno(EFAULT));
 217  212  
 218  213                  error = nfs_getfh(STRUCT_BUF(nga), get_udatamodel(), CRED());
 219  214                  break;
 220  215          }
 221  216  
 222  217          case NFS_REVAUTH: { /* revoke the cached credentials for the uid */
 223  218                  STRUCT_DECL(nfs_revauth_args, nra);
 224  219  
 225  220                  STRUCT_INIT(nra, get_udatamodel());
 226  221                  if (copyin(arg, STRUCT_BUF(nra), STRUCT_SIZE(nra)))
 227  222                          return (set_errno(EFAULT));
 228  223  
 229  224                  /* This call performs its own privilege checking */
 230  225                  error = sec_clnt_revoke(STRUCT_FGET(nra, authtype),
 231  226                      STRUCT_FGET(nra, uid), CRED(), NULL, get_udatamodel());
 232  227                  break;
 233  228          }
 234  229  
 235  230          case LM_SVC: { /* LM server daemon */
 236  231                  struct lm_svc_args lsa;
 237  232  
 238  233                  if (get_udatamodel() != DATAMODEL_NATIVE) {
 239  234                          STRUCT_DECL(lm_svc_args, ulsa);
 240  235  
 241  236                          STRUCT_INIT(ulsa, get_udatamodel());
 242  237                          if (copyin(arg, STRUCT_BUF(ulsa), STRUCT_SIZE(ulsa)))
 243  238                                  return (set_errno(EFAULT));
 244  239  
 245  240                          lsa.version = STRUCT_FGET(ulsa, version);
 246  241                          lsa.fd = STRUCT_FGET(ulsa, fd);
 247  242                          lsa.n_fmly = STRUCT_FGET(ulsa, n_fmly);
 248  243                          lsa.n_proto = STRUCT_FGET(ulsa, n_proto);
 249  244                          lsa.n_rdev = expldev(STRUCT_FGET(ulsa, n_rdev));
 250  245                          lsa.debug = STRUCT_FGET(ulsa, debug);
 251  246                          lsa.timout = STRUCT_FGET(ulsa, timout);
 252  247                          lsa.grace = STRUCT_FGET(ulsa, grace);
 253  248                          lsa.retransmittimeout = STRUCT_FGET(ulsa,
 254  249                              retransmittimeout);
 255  250                  } else {
 256  251                          if (copyin(arg, &lsa, sizeof (lsa)))
 257  252                                  return (set_errno(EFAULT));
 258  253                  }
 259  254  
 260  255                  error = lm_svc(&lsa);
 261  256                  break;
 262  257          }
 263  258  
 264  259          case KILL_LOCKMGR: {
 265  260                  error = lm_shutdown();
 266  261                  break;
 267  262          }
 268  263  
 269  264          case LOG_FLUSH: {       /* Flush log buffer and possibly rename */
 270  265                  STRUCT_DECL(nfsl_flush_args, nfa);
 271  266  
 272  267                  STRUCT_INIT(nfa, get_udatamodel());
 273  268                  if (copyin(arg, STRUCT_BUF(nfa), STRUCT_SIZE(nfa)))
 274  269                          return (set_errno(EFAULT));
 275  270  
 276  271                  error = nfsl_flush(STRUCT_BUF(nfa), get_udatamodel());
 277  272                  break;
 278  273          }
 279  274  
 280  275          case NFS4_SVC: { /* NFS client callback daemon */
 281  276  
 282  277                  STRUCT_DECL(nfs4_svc_args, nsa);
 283  278  
 284  279                  STRUCT_INIT(nsa, get_udatamodel());
 285  280  
 286  281                  if (copyin(arg, STRUCT_BUF(nsa), STRUCT_SIZE(nsa)))
 287  282                          return (set_errno(EFAULT));
 288  283  
 289  284                  error = nfs4_svc(STRUCT_BUF(nsa), get_udatamodel());
 290  285                  break;
 291  286          }
 292  287  
 293  288          /* Request that NFSv4 server quiesce on next shutdown */
 294  289          case NFS4_SVC_REQUEST_QUIESCE: {
 295  290                  int id;
 296  291  
 297  292                  /* check that nfssrv module is loaded */
 298  293                  if (nfs_srv_quiesce_func == NULL)
 299  294                          return (set_errno(ENOTSUP));
 300  295  
 301  296                  if (copyin(arg, &id, sizeof (id)))
 302  297                          return (set_errno(EFAULT));
 303  298  
 304  299                  error = svc_pool_control(id, SVCPSET_SHUTDOWN_PROC,
 305  300                      (void *)nfs_srv_quiesce_func);
 306  301                  break;
 307  302          }
 308  303  
 309  304          case NFS_IDMAP: {
 310  305                  struct nfsidmap_args idm;
 311  306  
 312  307                  if (copyin(arg, &idm, sizeof (idm)))
 313  308                          return (set_errno(EFAULT));
 314  309  
 315  310                  nfs_idmap_args(&idm);
 316  311                  error = 0;
 317  312                  break;
 318  313          }
 319  314  
 320  315          case NFS4_DSS_SETPATHS_SIZE: {
 321  316                  /* crosses ILP32/LP64 boundary */
 322  317                  uint32_t nfs4_dss_bufsize = 0;
 323  318  
 324  319                  if (copyin(arg, &nfs4_dss_bufsize, sizeof (nfs4_dss_bufsize)))
 325  320                          return (set_errno(EFAULT));
 326  321                  nfs4_dss_buflen = (long)nfs4_dss_bufsize;
 327  322                  error = 0;
 328  323                  break;
 329  324          }
 330  325  
 331  326          case NFS4_DSS_SETPATHS: {
 332  327                  char *nfs4_dss_bufp;
 333  328  
 334  329                  /* check that nfssrv module is loaded */
 335  330                  if (nfs_srv_dss_func == NULL)
 336  331                          return (set_errno(ENOTSUP));
 337  332  
 338  333                  /*
 339  334                   * NFS4_DSS_SETPATHS_SIZE must be called before
 340  335                   * NFS4_DSS_SETPATHS, to tell us how big a buffer we need
 341  336                   * to allocate.
 342  337                   */
 343  338                  if (nfs4_dss_buflen == 0)
 344  339                          return (set_errno(EINVAL));
 345  340                  nfs4_dss_bufp = kmem_alloc(nfs4_dss_buflen, KM_SLEEP);
 346  341                  if (nfs4_dss_bufp == NULL)
 347  342                          return (set_errno(ENOMEM));
 348  343  
 349  344                  if (copyin(arg, nfs4_dss_bufp, nfs4_dss_buflen)) {
 350  345                          kmem_free(nfs4_dss_bufp, nfs4_dss_buflen);
 351  346                          return (set_errno(EFAULT));
 352  347                  }
 353  348  
 354  349                  /* unpack the buffer and extract the pathnames */
 355  350                  error = nfs_srv_dss_func(nfs4_dss_bufp, nfs4_dss_buflen);
 356  351                  kmem_free(nfs4_dss_bufp, nfs4_dss_buflen);
 357  352  
 358  353                  break;
 359  354          }
 360  355  
 361  356          case NFS4_EPHEMERAL_MOUNT_TO: {
 362  357                  uint_t  mount_to;
 363  358  
 364  359                  /*
 365  360                   * Not a very complicated call.
 366  361                   */
 367  362                  if (copyin(arg, &mount_to, sizeof (mount_to)))
 368  363                          return (set_errno(EFAULT));
 369  364                  nfs4_ephemeral_set_mount_to(mount_to);
 370  365                  error = 0;
 371  366                  break;
 372  367          }
 373  368  
 374  369          case MOUNTD_ARGS: {
 375  370                  uint_t  did;
 376  371  
 377  372                  /*
 378  373                   * For now, only passing down the door fd; if we
 379  374                   * ever need to pass down more info, we can use
 380  375                   * a (properly aligned) struct.
 381  376                   */
 382  377                  if (copyin(arg, &did, sizeof (did)))
 383  378                          return (set_errno(EFAULT));
 384  379                  mountd_args(did);
 385  380                  error = 0;
 386  381                  break;
 387  382          }
 388  383  
 389  384          case NFSCMD_ARGS: {
 390  385                  uint_t  did;
 391  386  
 392  387                  /*
 393  388                   * For now, only passing down the door fd; if we
 394  389                   * ever need to pass down more info, we can use
 395  390                   * a (properly aligned) struct.
 396  391                   */
 397  392                  if (copyin(arg, &did, sizeof (did)))
 398  393                          return (set_errno(EFAULT));
 399  394                  nfscmd_args(did);
 400  395                  error = 0;
 401  396                  break;
 402  397          }
 403  398  
 404  399          default:
 405  400                  error = EINVAL;
 406  401                  break;
 407  402          }
 408  403  
 409  404          return ((error != 0) ? set_errno(error) : 0);
 410  405  }
  
    | 
      ↓ open down ↓ | 
    187 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX