Print this page
    
*** NO COMMENTS ***
    
      
        | Split | Close | 
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/fs/nfs/nfs3_srv.c
          +++ new/usr/src/uts/common/fs/nfs/nfs3_srv.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
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
  23   23   */
  24   24  
  25   25  /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
  26   26  /* All Rights Reserved */
  27   27  
  28   28  #include <sys/param.h>
  29   29  #include <sys/types.h>
  30   30  #include <sys/systm.h>
  31   31  #include <sys/cred.h>
  32   32  #include <sys/buf.h>
  33   33  #include <sys/vfs.h>
  34   34  #include <sys/vnode.h>
  35   35  #include <sys/uio.h>
  36   36  #include <sys/errno.h>
  37   37  #include <sys/sysmacros.h>
  38   38  #include <sys/statvfs.h>
  39   39  #include <sys/kmem.h>
  40   40  #include <sys/dirent.h>
  41   41  #include <sys/cmn_err.h>
  42   42  #include <sys/debug.h>
  43   43  #include <sys/systeminfo.h>
  44   44  #include <sys/flock.h>
  45   45  #include <sys/nbmlock.h>
  46   46  #include <sys/policy.h>
  47   47  #include <sys/sdt.h>
  48   48  
  49   49  #include <rpc/types.h>
  50   50  #include <rpc/auth.h>
  51   51  #include <rpc/svc.h>
  52   52  #include <rpc/rpc_rdma.h>
  53   53  
  54   54  #include <nfs/nfs.h>
  55   55  #include <nfs/export.h>
  56   56  #include <nfs/nfs_cmd.h>
  57   57  
  58   58  #include <sys/strsubr.h>
  59   59  
  60   60  #include <sys/tsol/label.h>
  61   61  #include <sys/tsol/tndb.h>
  62   62  
  63   63  #include <sys/zone.h>
  
    | ↓ open down ↓ | 63 lines elided | ↑ open up ↑ | 
  64   64  
  65   65  #include <inet/ip.h>
  66   66  #include <inet/ip6.h>
  67   67  
  68   68  /*
  69   69   * These are the interface routines for the server side of the
  70   70   * Network File System.  See the NFS version 3 protocol specification
  71   71   * for a description of this interface.
  72   72   */
  73   73  
  74      -#ifdef DEBUG
  75      -int rfs3_do_pre_op_attr = 1;
  76      -int rfs3_do_post_op_attr = 1;
  77      -int rfs3_do_post_op_fh3 = 1;
  78      -#endif
  79      -
  80   74  static writeverf3 write3verf;
  81   75  
  82   76  static int      sattr3_to_vattr(sattr3 *, struct vattr *);
  83   77  static int      vattr_to_fattr3(struct vattr *, fattr3 *);
  84   78  static int      vattr_to_wcc_attr(struct vattr *, wcc_attr *);
  85   79  static void     vattr_to_pre_op_attr(struct vattr *, pre_op_attr *);
  86   80  static void     vattr_to_wcc_data(struct vattr *, struct vattr *, wcc_data *);
  87   81  static int      rdma_setup_read_data3(READ3args *, READ3resok *);
  88   82  
  89   83  extern int nfs_loaned_buffers;
  90   84  
  91   85  u_longlong_t nfs3_srv_caller_id;
  92   86  
  93   87  /* ARGSUSED */
  94   88  void
  95   89  rfs3_getattr(GETATTR3args *args, GETATTR3res *resp, struct exportinfo *exi,
  96   90          struct svc_req *req, cred_t *cr)
  97   91  {
  98   92          int error;
  99   93          vnode_t *vp;
 100   94          struct vattr va;
 101   95  
 102   96          vp = nfs3_fhtovp(&args->object, exi);
 103   97  
 104   98          DTRACE_NFSV3_4(op__getattr__start, struct svc_req *, req,
 105   99              cred_t *, cr, vnode_t *, vp, GETATTR3args *, args);
 106  100  
 107  101          if (vp == NULL) {
 108  102                  error = ESTALE;
 109  103                  goto out;
 110  104          }
 111  105  
 112  106          va.va_mask = AT_ALL;
 113  107          error = rfs4_delegated_getattr(vp, &va, 0, cr);
 114  108  
 115  109          if (!error) {
 116  110                  /* Lie about the object type for a referral */
 117  111                  if (vn_is_nfs_reparse(vp, cr))
 118  112                          va.va_type = VLNK;
 119  113  
 120  114                  /* overflow error if time or size is out of range */
 121  115                  error = vattr_to_fattr3(&va, &resp->resok.obj_attributes);
 122  116                  if (error)
 123  117                          goto out;
 124  118                  resp->status = NFS3_OK;
 125  119  
 126  120                  DTRACE_NFSV3_4(op__getattr__done, struct svc_req *, req,
 127  121                      cred_t *, cr, vnode_t *, vp, GETATTR3res *, resp);
 128  122  
 129  123                  VN_RELE(vp);
 130  124  
 131  125                  return;
 132  126          }
 133  127  
 134  128  out:
 135  129          if (curthread->t_flag & T_WOULDBLOCK) {
 136  130                  curthread->t_flag &= ~T_WOULDBLOCK;
 137  131                  resp->status = NFS3ERR_JUKEBOX;
 138  132          } else
 139  133                  resp->status = puterrno3(error);
 140  134  
 141  135          DTRACE_NFSV3_4(op__getattr__done, struct svc_req *, req,
 142  136              cred_t *, cr, vnode_t *, vp, GETATTR3res *, resp);
 143  137  
 144  138          if (vp != NULL)
 145  139                  VN_RELE(vp);
 146  140  }
 147  141  
 148  142  void *
 149  143  rfs3_getattr_getfh(GETATTR3args *args)
 150  144  {
 151  145  
 152  146          return (&args->object);
 153  147  }
 154  148  
 155  149  void
 156  150  rfs3_setattr(SETATTR3args *args, SETATTR3res *resp, struct exportinfo *exi,
 157  151          struct svc_req *req, cred_t *cr)
 158  152  {
 159  153          int error;
 160  154          vnode_t *vp;
 161  155          struct vattr *bvap;
 162  156          struct vattr bva;
 163  157          struct vattr *avap;
 164  158          struct vattr ava;
 165  159          int flag;
 166  160          int in_crit = 0;
 167  161          struct flock64 bf;
 168  162          caller_context_t ct;
 169  163  
 170  164          bvap = NULL;
 171  165          avap = NULL;
 172  166  
 173  167          vp = nfs3_fhtovp(&args->object, exi);
 174  168  
 175  169          DTRACE_NFSV3_4(op__setattr__start, struct svc_req *, req,
 176  170              cred_t *, cr, vnode_t *, vp, SETATTR3args *, args);
 177  171  
 178  172          if (vp == NULL) {
 179  173                  error = ESTALE;
 180  174                  goto out;
 181  175          }
 182  176  
 183  177          error = sattr3_to_vattr(&args->new_attributes, &ava);
 184  178          if (error)
 185  179                  goto out;
 186  180  
 187  181          if (is_system_labeled()) {
 188  182                  bslabel_t *clabel = req->rq_label;
 189  183  
 190  184                  ASSERT(clabel != NULL);
 191  185                  DTRACE_PROBE2(tx__rfs3__log__info__opsetattr__clabel, char *,
 192  186                      "got client label from request(1)", struct svc_req *, req);
 193  187  
 194  188                  if (!blequal(&l_admin_low->tsl_label, clabel)) {
 195  189                          if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
 196  190                              exi)) {
 197  191                                  resp->status = NFS3ERR_ACCES;
 198  192                                  goto out1;
 199  193                          }
 200  194                  }
 201  195          }
 202  196  
 203  197          /*
 204  198           * We need to specially handle size changes because of
 205  199           * possible conflicting NBMAND locks. Get into critical
 206  200           * region before VOP_GETATTR, so the size attribute is
 207  201           * valid when checking conflicts.
 208  202           *
 209  203           * Also, check to see if the v4 side of the server has
 210  204           * delegated this file.  If so, then we return JUKEBOX to
 211  205           * allow the client to retrasmit its request.
 212  206           */
 213  207          if (vp->v_type == VREG && (ava.va_mask & AT_SIZE)) {
 214  208                  if (nbl_need_check(vp)) {
 215  209                          nbl_start_crit(vp, RW_READER);
 216  210                          in_crit = 1;
 217  211                  }
 218  212          }
 219  213  
  
    | ↓ open down ↓ | 130 lines elided | ↑ open up ↑ | 
 220  214          bva.va_mask = AT_ALL;
 221  215          error = rfs4_delegated_getattr(vp, &bva, 0, cr);
 222  216  
 223  217          /*
 224  218           * If we can't get the attributes, then we can't do the
 225  219           * right access checking.  So, we'll fail the request.
 226  220           */
 227  221          if (error)
 228  222                  goto out;
 229  223  
 230      -#ifdef DEBUG
 231      -        if (rfs3_do_pre_op_attr)
 232      -                bvap = &bva;
 233      -#else
 234  224          bvap = &bva;
 235      -#endif
 236  225  
 237  226          if (rdonly(exi, req) || vn_is_readonly(vp)) {
 238  227                  resp->status = NFS3ERR_ROFS;
 239  228                  goto out1;
 240  229          }
 241  230  
 242  231          if (args->guard.check &&
 243  232              (args->guard.obj_ctime.seconds != bva.va_ctime.tv_sec ||
 244  233              args->guard.obj_ctime.nseconds != bva.va_ctime.tv_nsec)) {
 245  234                  resp->status = NFS3ERR_NOT_SYNC;
 246  235                  goto out1;
 247  236          }
 248  237  
 249  238          if (args->new_attributes.mtime.set_it == SET_TO_CLIENT_TIME)
 250  239                  flag = ATTR_UTIME;
 251  240          else
 252  241                  flag = 0;
 253  242  
 254  243          /*
 255  244           * If the filesystem is exported with nosuid, then mask off
 256  245           * the setuid and setgid bits.
 257  246           */
 258  247          if ((ava.va_mask & AT_MODE) && vp->v_type == VREG &&
 259  248              (exi->exi_export.ex_flags & EX_NOSUID))
 260  249                  ava.va_mode &= ~(VSUID | VSGID);
 261  250  
 262  251          ct.cc_sysid = 0;
 263  252          ct.cc_pid = 0;
 264  253          ct.cc_caller_id = nfs3_srv_caller_id;
 265  254          ct.cc_flags = CC_DONTBLOCK;
 266  255  
 267  256          /*
 268  257           * We need to specially handle size changes because it is
 269  258           * possible for the client to create a file with modes
 270  259           * which indicate read-only, but with the file opened for
 271  260           * writing.  If the client then tries to set the size of
 272  261           * the file, then the normal access checking done in
 273  262           * VOP_SETATTR would prevent the client from doing so,
 274  263           * although it should be legal for it to do so.  To get
 275  264           * around this, we do the access checking for ourselves
 276  265           * and then use VOP_SPACE which doesn't do the access
 277  266           * checking which VOP_SETATTR does. VOP_SPACE can only
 278  267           * operate on VREG files, let VOP_SETATTR handle the other
 279  268           * extremely rare cases.
 280  269           * Also the client should not be allowed to change the
 281  270           * size of the file if there is a conflicting non-blocking
 282  271           * mandatory lock in the region the change.
 283  272           */
 284  273          if (vp->v_type == VREG && (ava.va_mask & AT_SIZE)) {
 285  274                  if (in_crit) {
 286  275                          u_offset_t offset;
 287  276                          ssize_t length;
 288  277  
 289  278                          if (ava.va_size < bva.va_size) {
 290  279                                  offset = ava.va_size;
 291  280                                  length = bva.va_size - ava.va_size;
 292  281                          } else {
 293  282                                  offset = bva.va_size;
 294  283                                  length = ava.va_size - bva.va_size;
 295  284                          }
 296  285                          if (nbl_conflict(vp, NBL_WRITE, offset, length, 0,
 297  286                              NULL)) {
 298  287                                  error = EACCES;
 299  288                                  goto out;
 300  289                          }
 301  290                  }
 302  291  
 303  292                  if (crgetuid(cr) == bva.va_uid && ava.va_size != bva.va_size) {
 304  293                          ava.va_mask &= ~AT_SIZE;
 305  294                          bf.l_type = F_WRLCK;
 306  295                          bf.l_whence = 0;
 307  296                          bf.l_start = (off64_t)ava.va_size;
 308  297                          bf.l_len = 0;
 309  298                          bf.l_sysid = 0;
 310  299                          bf.l_pid = 0;
 311  300                          error = VOP_SPACE(vp, F_FREESP, &bf, FWRITE,
 312  301                              (offset_t)ava.va_size, cr, &ct);
 313  302                  }
 314  303          }
  
    | ↓ open down ↓ | 69 lines elided | ↑ open up ↑ | 
 315  304  
 316  305          if (!error && ava.va_mask)
 317  306                  error = VOP_SETATTR(vp, &ava, flag, cr, &ct);
 318  307  
 319  308          /* check if a monitor detected a delegation conflict */
 320  309          if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
 321  310                  resp->status = NFS3ERR_JUKEBOX;
 322  311                  goto out1;
 323  312          }
 324  313  
 325      -#ifdef DEBUG
 326      -        if (rfs3_do_post_op_attr) {
 327      -                ava.va_mask = AT_ALL;
 328      -                avap = rfs4_delegated_getattr(vp, &ava, 0, cr) ? NULL : &ava;
 329      -        } else
 330      -                avap = NULL;
 331      -#else
 332  314          ava.va_mask = AT_ALL;
 333  315          avap = rfs4_delegated_getattr(vp, &ava, 0, cr) ? NULL : &ava;
 334      -#endif
 335  316  
 336  317          /*
 337  318           * Force modified metadata out to stable storage.
 338  319           */
 339  320          (void) VOP_FSYNC(vp, FNODSYNC, cr, &ct);
 340  321  
 341  322          if (error)
 342  323                  goto out;
 343  324  
 344  325          if (in_crit)
 345  326                  nbl_end_crit(vp);
 346  327  
 347  328          resp->status = NFS3_OK;
 348  329          vattr_to_wcc_data(bvap, avap, &resp->resok.obj_wcc);
 349  330  
 350  331          DTRACE_NFSV3_4(op__setattr__done, struct svc_req *, req,
 351  332              cred_t *, cr, vnode_t *, vp, SETATTR3res *, resp);
 352  333  
 353  334          VN_RELE(vp);
 354  335  
 355  336          return;
 356  337  
 357  338  out:
 358  339          if (curthread->t_flag & T_WOULDBLOCK) {
 359  340                  curthread->t_flag &= ~T_WOULDBLOCK;
 360  341                  resp->status = NFS3ERR_JUKEBOX;
 361  342          } else
 362  343                  resp->status = puterrno3(error);
 363  344  out1:
 364  345          DTRACE_NFSV3_4(op__setattr__done, struct svc_req *, req,
 365  346              cred_t *, cr, vnode_t *, vp, SETATTR3res *, resp);
 366  347  
 367  348          if (vp != NULL) {
 368  349                  if (in_crit)
 369  350                          nbl_end_crit(vp);
 370  351                  VN_RELE(vp);
 371  352          }
 372  353          vattr_to_wcc_data(bvap, avap, &resp->resfail.obj_wcc);
 373  354  }
 374  355  
 375  356  void *
 376  357  rfs3_setattr_getfh(SETATTR3args *args)
 377  358  {
 378  359  
 379  360          return (&args->object);
 380  361  }
 381  362  
 382  363  /* ARGSUSED */
 383  364  void
 384  365  rfs3_lookup(LOOKUP3args *args, LOOKUP3res *resp, struct exportinfo *exi,
 385  366          struct svc_req *req, cred_t *cr)
 386  367  {
 387  368          int error;
 388  369          vnode_t *vp;
 389  370          vnode_t *dvp;
 390  371          struct vattr *vap;
 391  372          struct vattr va;
 392  373          struct vattr *dvap;
 393  374          struct vattr dva;
 394  375          nfs_fh3 *fhp;
 395  376          struct sec_ol sec = {0, 0};
 396  377          bool_t publicfh_flag = FALSE, auth_weak = FALSE;
 397  378          struct sockaddr *ca;
 398  379          char *name = NULL;
 399  380  
 400  381          dvap = NULL;
 401  382  
 402  383          /*
 403  384           * Allow lookups from the root - the default
 404  385           * location of the public filehandle.
 405  386           */
 406  387          if (exi != NULL && (exi->exi_export.ex_flags & EX_PUBLIC)) {
 407  388                  dvp = rootdir;
 408  389                  VN_HOLD(dvp);
 409  390  
 410  391                  DTRACE_NFSV3_4(op__lookup__start, struct svc_req *, req,
 411  392                      cred_t *, cr, vnode_t *, dvp, LOOKUP3args *, args);
 412  393          } else {
 413  394                  dvp = nfs3_fhtovp(&args->what.dir, exi);
  
    | ↓ open down ↓ | 69 lines elided | ↑ open up ↑ | 
 414  395  
 415  396                  DTRACE_NFSV3_4(op__lookup__start, struct svc_req *, req,
 416  397                      cred_t *, cr, vnode_t *, dvp, LOOKUP3args *, args);
 417  398  
 418  399                  if (dvp == NULL) {
 419  400                          error = ESTALE;
 420  401                          goto out;
 421  402                  }
 422  403          }
 423  404  
 424      -#ifdef DEBUG
 425      -        if (rfs3_do_pre_op_attr) {
 426      -                dva.va_mask = AT_ALL;
 427      -                dvap = VOP_GETATTR(dvp, &dva, 0, cr, NULL) ? NULL : &dva;
 428      -        }
 429      -#else
 430  405          dva.va_mask = AT_ALL;
 431  406          dvap = VOP_GETATTR(dvp, &dva, 0, cr, NULL) ? NULL : &dva;
 432      -#endif
 433  407  
 434  408          if (args->what.name == nfs3nametoolong) {
 435  409                  resp->status = NFS3ERR_NAMETOOLONG;
 436  410                  goto out1;
 437  411          }
 438  412  
 439  413          if (args->what.name == NULL || *(args->what.name) == '\0') {
 440  414                  resp->status = NFS3ERR_ACCES;
 441  415                  goto out1;
 442  416          }
 443  417  
 444  418          fhp = &args->what.dir;
 445  419          if (strcmp(args->what.name, "..") == 0 &&
 446  420              EQFID(&exi->exi_fid, FH3TOFIDP(fhp))) {
 447  421                  resp->status = NFS3ERR_NOENT;
 448  422                  goto out1;
 449  423          }
  
    | ↓ open down ↓ | 7 lines elided | ↑ open up ↑ | 
 450  424  
 451  425          ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
 452  426          name = nfscmd_convname(ca, exi, args->what.name,
 453  427              NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
 454  428  
 455  429          if (name == NULL) {
 456  430                  resp->status = NFS3ERR_ACCES;
 457  431                  goto out1;
 458  432          }
 459  433  
      434 +        exi_hold(exi);
      435 +
 460  436          /*
 461  437           * If the public filehandle is used then allow
 462  438           * a multi-component lookup
 463  439           */
 464  440          if (PUBLIC_FH3(&args->what.dir)) {
      441 +                struct exportinfo *new;
      442 +
 465  443                  publicfh_flag = TRUE;
      444 +
 466  445                  error = rfs_publicfh_mclookup(name, dvp, cr, &vp,
 467      -                    &exi, &sec);
 468      -                if (error && exi != NULL)
 469      -                        exi_rele(exi); /* See comment below Re: publicfh_flag */
      446 +                    &new, &sec);
      447 +
      448 +                if (error == 0) {
      449 +                        exi_rele(exi);
      450 +                        exi = new;
      451 +                }
      452 +
 470  453                  /*
 471  454                   * Since WebNFS may bypass MOUNT, we need to ensure this
 472  455                   * request didn't come from an unlabeled admin_low client.
 473  456                   */
 474  457                  if (is_system_labeled() && error == 0) {
 475  458                          int             addr_type;
 476  459                          void            *ipaddr;
 477  460                          tsol_tpc_t      *tp;
 478  461  
 479  462                          if (ca->sa_family == AF_INET) {
 480  463                                  addr_type = IPV4_VERSION;
  
    | ↓ open down ↓ | 1 lines elided | ↑ open up ↑ | 
 481  464                                  ipaddr = &((struct sockaddr_in *)ca)->sin_addr;
 482  465                          } else if (ca->sa_family == AF_INET6) {
 483  466                                  addr_type = IPV6_VERSION;
 484  467                                  ipaddr = &((struct sockaddr_in6 *)
 485  468                                      ca)->sin6_addr;
 486  469                          }
 487  470                          tp = find_tpc(ipaddr, addr_type, B_FALSE);
 488  471                          if (tp == NULL || tp->tpc_tp.tp_doi !=
 489  472                              l_admin_low->tsl_doi || tp->tpc_tp.host_type !=
 490  473                              SUN_CIPSO) {
 491      -                                if (exi != NULL)
 492      -                                        exi_rele(exi);
 493  474                                  VN_RELE(vp);
 494  475                                  resp->status = NFS3ERR_ACCES;
 495  476                                  error = 1;
 496  477                          }
 497  478                          if (tp != NULL)
 498  479                                  TPC_RELE(tp);
 499  480                  }
 500  481          } else {
 501  482                  error = VOP_LOOKUP(dvp, name, &vp,
 502  483                      NULL, 0, NULL, cr, NULL, NULL, NULL);
 503  484          }
 504  485  
 505  486          if (name != args->what.name)
 506  487                  kmem_free(name, MAXPATHLEN + 1);
 507  488  
      489 +        if (error == 0 && vn_ismntpt(vp)) {
      490 +                error = rfs_cross_mnt(&vp, &exi);
      491 +                if (error)
      492 +                        VN_RELE(vp);
      493 +        }
      494 +
 508  495          if (is_system_labeled() && error == 0) {
 509  496                  bslabel_t *clabel = req->rq_label;
 510  497  
 511  498                  ASSERT(clabel != NULL);
 512  499                  DTRACE_PROBE2(tx__rfs3__log__info__oplookup__clabel, char *,
 513  500                      "got client label from request(1)", struct svc_req *, req);
 514  501  
 515  502                  if (!blequal(&l_admin_low->tsl_label, clabel)) {
 516  503                          if (!do_rfs_label_check(clabel, dvp,
 517  504                              DOMINANCE_CHECK, exi)) {
 518      -                                if (publicfh_flag && exi != NULL)
 519      -                                        exi_rele(exi);
 520  505                                  VN_RELE(vp);
 521  506                                  resp->status = NFS3ERR_ACCES;
 522  507                                  error = 1;
 523  508                          }
 524  509                  }
 525  510          }
 526  511  
 527      -#ifdef DEBUG
 528      -        if (rfs3_do_post_op_attr) {
 529      -                dva.va_mask = AT_ALL;
 530      -                dvap = VOP_GETATTR(dvp, &dva, 0, cr, NULL) ? NULL : &dva;
 531      -        } else
 532      -                dvap = NULL;
 533      -#else
 534  512          dva.va_mask = AT_ALL;
 535  513          dvap = VOP_GETATTR(dvp, &dva, 0, cr, NULL) ? NULL : &dva;
 536      -#endif
 537  514  
 538  515          if (error)
 539  516                  goto out;
 540  517  
 541  518          if (sec.sec_flags & SEC_QUERY) {
 542  519                  error = makefh3_ol(&resp->resok.object, exi, sec.sec_index);
 543  520          } else {
 544  521                  error = makefh3(&resp->resok.object, vp, exi);
 545  522                  if (!error && publicfh_flag && !chk_clnt_sec(exi, req))
 546  523                          auth_weak = TRUE;
 547  524          }
 548  525  
 549  526          if (error) {
 550  527                  VN_RELE(vp);
 551  528                  goto out;
 552  529          }
 553  530  
 554      -        /*
 555      -         * If publicfh_flag is true then we have called rfs_publicfh_mclookup
 556      -         * and have obtained a new exportinfo in exi which needs to be
 557      -         * released. Note the the original exportinfo pointed to by exi
 558      -         * will be released by the caller, common_dispatch.
 559      -         */
 560      -        if (publicfh_flag)
 561      -                exi_rele(exi);
 562      -
 563      -#ifdef DEBUG
 564      -        if (rfs3_do_post_op_attr) {
 565      -                va.va_mask = AT_ALL;
 566      -                vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
 567      -        } else
 568      -                vap = NULL;
 569      -#else
 570  531          va.va_mask = AT_ALL;
 571  532          vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
 572      -#endif
 573  533  
      534 +        exi_rele(exi);
 574  535          VN_RELE(vp);
 575  536  
 576  537          resp->status = NFS3_OK;
 577  538          vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
 578  539          vattr_to_post_op_attr(dvap, &resp->resok.dir_attributes);
 579  540  
 580  541          /*
 581  542           * If it's public fh, no 0x81, and client's flavor is
 582  543           * invalid, set WebNFS status to WNFSERR_CLNT_FLAVOR now.
 583  544           * Then set RPC status to AUTH_TOOWEAK in common_dispatch.
 584  545           */
  
    | ↓ open down ↓ | 1 lines elided | ↑ open up ↑ | 
 585  546          if (auth_weak)
 586  547                  resp->status = (enum nfsstat3)WNFSERR_CLNT_FLAVOR;
 587  548  
 588  549          DTRACE_NFSV3_4(op__lookup__done, struct svc_req *, req,
 589  550              cred_t *, cr, vnode_t *, dvp, LOOKUP3res *, resp);
 590  551          VN_RELE(dvp);
 591  552  
 592  553          return;
 593  554  
 594  555  out:
      556 +        /*
      557 +         * The passed argument exportinfo is released by the
      558 +         * caller, common_dispatch
      559 +         */
      560 +        exi_rele(exi);
      561 +
 595  562          if (curthread->t_flag & T_WOULDBLOCK) {
 596  563                  curthread->t_flag &= ~T_WOULDBLOCK;
 597  564                  resp->status = NFS3ERR_JUKEBOX;
 598  565          } else
 599  566                  resp->status = puterrno3(error);
 600  567  out1:
 601  568          DTRACE_NFSV3_4(op__lookup__done, struct svc_req *, req,
 602  569              cred_t *, cr, vnode_t *, dvp, LOOKUP3res *, resp);
 603  570  
 604  571          if (dvp != NULL)
 605  572                  VN_RELE(dvp);
 606  573          vattr_to_post_op_attr(dvap, &resp->resfail.dir_attributes);
 607  574  
 608  575  }
 609  576  
 610  577  void *
 611  578  rfs3_lookup_getfh(LOOKUP3args *args)
 612  579  {
 613  580  
 614  581          return (&args->what.dir);
 615  582  }
 616  583  
 617  584  /* ARGSUSED */
 618  585  void
 619  586  rfs3_access(ACCESS3args *args, ACCESS3res *resp, struct exportinfo *exi,
 620  587          struct svc_req *req, cred_t *cr)
 621  588  {
 622  589          int error;
 623  590          vnode_t *vp;
 624  591          struct vattr *vap;
 625  592          struct vattr va;
 626  593          int checkwriteperm;
 627  594          boolean_t dominant_label = B_FALSE;
 628  595          boolean_t equal_label = B_FALSE;
 629  596          boolean_t admin_low_client;
 630  597  
 631  598          vap = NULL;
 632  599  
 633  600          vp = nfs3_fhtovp(&args->object, exi);
 634  601  
 635  602          DTRACE_NFSV3_4(op__access__start, struct svc_req *, req,
 636  603              cred_t *, cr, vnode_t *, vp, ACCESS3args *, args);
 637  604  
 638  605          if (vp == NULL) {
 639  606                  error = ESTALE;
 640  607                  goto out;
 641  608          }
 642  609  
 643  610          /*
 644  611           * If the file system is exported read only, it is not appropriate
 645  612           * to check write permissions for regular files and directories.
 646  613           * Special files are interpreted by the client, so the underlying
 647  614           * permissions are sent back to the client for interpretation.
 648  615           */
 649  616          if (rdonly(exi, req) && (vp->v_type == VREG || vp->v_type == VDIR))
 650  617                  checkwriteperm = 0;
 651  618          else
 652  619                  checkwriteperm = 1;
 653  620  
 654  621          /*
  
    | ↓ open down ↓ | 50 lines elided | ↑ open up ↑ | 
 655  622           * We need the mode so that we can correctly determine access
 656  623           * permissions relative to a mandatory lock file.  Access to
 657  624           * mandatory lock files is denied on the server, so it might
 658  625           * as well be reflected to the server during the open.
 659  626           */
 660  627          va.va_mask = AT_MODE;
 661  628          error = VOP_GETATTR(vp, &va, 0, cr, NULL);
 662  629          if (error)
 663  630                  goto out;
 664  631  
 665      -#ifdef DEBUG
 666      -        if (rfs3_do_post_op_attr)
 667      -                vap = &va;
 668      -#else
 669  632          vap = &va;
 670      -#endif
 671  633  
 672  634          resp->resok.access = 0;
 673  635  
 674  636          if (is_system_labeled()) {
 675  637                  bslabel_t *clabel = req->rq_label;
 676  638  
 677  639                  ASSERT(clabel != NULL);
 678  640                  DTRACE_PROBE2(tx__rfs3__log__info__opaccess__clabel, char *,
 679  641                      "got client label from request(1)", struct svc_req *, req);
 680  642  
 681  643                  if (!blequal(&l_admin_low->tsl_label, clabel)) {
 682  644                          if ((equal_label = do_rfs_label_check(clabel, vp,
 683  645                              EQUALITY_CHECK, exi)) == B_FALSE) {
 684  646                                  dominant_label = do_rfs_label_check(clabel,
 685  647                                      vp, DOMINANCE_CHECK, exi);
 686  648                          } else
 687  649                                  dominant_label = B_TRUE;
 688  650                          admin_low_client = B_FALSE;
 689  651                  } else
 690  652                          admin_low_client = B_TRUE;
 691  653          }
 692  654  
 693  655          if (args->access & ACCESS3_READ) {
 694  656                  error = VOP_ACCESS(vp, VREAD, 0, cr, NULL);
 695  657                  if (error) {
 696  658                          if (curthread->t_flag & T_WOULDBLOCK)
 697  659                                  goto out;
 698  660                  } else if (!MANDLOCK(vp, va.va_mode) &&
 699  661                      (!is_system_labeled() || admin_low_client ||
 700  662                      dominant_label))
 701  663                          resp->resok.access |= ACCESS3_READ;
 702  664          }
 703  665          if ((args->access & ACCESS3_LOOKUP) && vp->v_type == VDIR) {
 704  666                  error = VOP_ACCESS(vp, VEXEC, 0, cr, NULL);
 705  667                  if (error) {
 706  668                          if (curthread->t_flag & T_WOULDBLOCK)
 707  669                                  goto out;
 708  670                  } else if (!is_system_labeled() || admin_low_client ||
 709  671                      dominant_label)
 710  672                          resp->resok.access |= ACCESS3_LOOKUP;
 711  673          }
 712  674          if (checkwriteperm &&
 713  675              (args->access & (ACCESS3_MODIFY|ACCESS3_EXTEND))) {
 714  676                  error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL);
 715  677                  if (error) {
 716  678                          if (curthread->t_flag & T_WOULDBLOCK)
 717  679                                  goto out;
 718  680                  } else if (!MANDLOCK(vp, va.va_mode) &&
 719  681                      (!is_system_labeled() || admin_low_client || equal_label)) {
 720  682                          resp->resok.access |=
 721  683                              (args->access & (ACCESS3_MODIFY|ACCESS3_EXTEND));
 722  684                  }
 723  685          }
 724  686          if (checkwriteperm &&
 725  687              (args->access & ACCESS3_DELETE) && vp->v_type == VDIR) {
 726  688                  error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL);
 727  689                  if (error) {
 728  690                          if (curthread->t_flag & T_WOULDBLOCK)
 729  691                                  goto out;
 730  692                  } else if (!is_system_labeled() || admin_low_client ||
 731  693                      equal_label)
 732  694                          resp->resok.access |= ACCESS3_DELETE;
 733  695          }
 734  696          if (args->access & ACCESS3_EXECUTE) {
  
    | ↓ open down ↓ | 54 lines elided | ↑ open up ↑ | 
 735  697                  error = VOP_ACCESS(vp, VEXEC, 0, cr, NULL);
 736  698                  if (error) {
 737  699                          if (curthread->t_flag & T_WOULDBLOCK)
 738  700                                  goto out;
 739  701                  } else if (!MANDLOCK(vp, va.va_mode) &&
 740  702                      (!is_system_labeled() || admin_low_client ||
 741  703                      dominant_label))
 742  704                          resp->resok.access |= ACCESS3_EXECUTE;
 743  705          }
 744  706  
 745      -#ifdef DEBUG
 746      -        if (rfs3_do_post_op_attr) {
 747      -                va.va_mask = AT_ALL;
 748      -                vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
 749      -        } else
 750      -                vap = NULL;
 751      -#else
 752  707          va.va_mask = AT_ALL;
 753  708          vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
 754      -#endif
 755  709  
 756  710          resp->status = NFS3_OK;
 757  711          vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
 758  712  
 759  713          DTRACE_NFSV3_4(op__access__done, struct svc_req *, req,
 760  714              cred_t *, cr, vnode_t *, vp, ACCESS3res *, resp);
 761  715  
 762  716          VN_RELE(vp);
 763  717  
 764  718          return;
 765  719  
 766  720  out:
 767  721          if (curthread->t_flag & T_WOULDBLOCK) {
 768  722                  curthread->t_flag &= ~T_WOULDBLOCK;
 769  723                  resp->status = NFS3ERR_JUKEBOX;
 770  724          } else
 771  725                  resp->status = puterrno3(error);
 772  726          DTRACE_NFSV3_4(op__access__done, struct svc_req *, req,
 773  727              cred_t *, cr, vnode_t *, vp, ACCESS3res *, resp);
 774  728          if (vp != NULL)
 775  729                  VN_RELE(vp);
 776  730          vattr_to_post_op_attr(vap, &resp->resfail.obj_attributes);
 777  731  }
 778  732  
 779  733  void *
 780  734  rfs3_access_getfh(ACCESS3args *args)
 781  735  {
 782  736  
 783  737          return (&args->object);
 784  738  }
 785  739  
 786  740  /* ARGSUSED */
 787  741  void
 788  742  rfs3_readlink(READLINK3args *args, READLINK3res *resp, struct exportinfo *exi,
 789  743          struct svc_req *req, cred_t *cr)
 790  744  {
 791  745          int error;
 792  746          vnode_t *vp;
 793  747          struct vattr *vap;
 794  748          struct vattr va;
 795  749          struct iovec iov;
 796  750          struct uio uio;
 797  751          char *data;
 798  752          struct sockaddr *ca;
 799  753          char *name = NULL;
 800  754          int is_referral = 0;
 801  755  
 802  756          vap = NULL;
 803  757  
 804  758          vp = nfs3_fhtovp(&args->symlink, exi);
 805  759  
 806  760          DTRACE_NFSV3_4(op__readlink__start, struct svc_req *, req,
 807  761              cred_t *, cr, vnode_t *, vp, READLINK3args *, args);
 808  762  
  
    | ↓ open down ↓ | 44 lines elided | ↑ open up ↑ | 
 809  763          if (vp == NULL) {
 810  764                  error = ESTALE;
 811  765                  goto out;
 812  766          }
 813  767  
 814  768          va.va_mask = AT_ALL;
 815  769          error = VOP_GETATTR(vp, &va, 0, cr, NULL);
 816  770          if (error)
 817  771                  goto out;
 818  772  
 819      -#ifdef DEBUG
 820      -        if (rfs3_do_post_op_attr)
 821      -                vap = &va;
 822      -#else
 823  773          vap = &va;
 824      -#endif
 825  774  
 826  775          /* We lied about the object type for a referral */
 827  776          if (vn_is_nfs_reparse(vp, cr))
 828  777                  is_referral = 1;
 829  778  
 830  779          if (vp->v_type != VLNK && !is_referral) {
 831  780                  resp->status = NFS3ERR_INVAL;
 832  781                  goto out1;
 833  782          }
 834  783  
 835  784          if (MANDLOCK(vp, va.va_mode)) {
 836  785                  resp->status = NFS3ERR_ACCES;
 837  786                  goto out1;
 838  787          }
 839  788  
 840  789          if (is_system_labeled()) {
 841  790                  bslabel_t *clabel = req->rq_label;
 842  791  
 843  792                  ASSERT(clabel != NULL);
 844  793                  DTRACE_PROBE2(tx__rfs3__log__info__opreadlink__clabel, char *,
 845  794                      "got client label from request(1)", struct svc_req *, req);
 846  795  
 847  796                  if (!blequal(&l_admin_low->tsl_label, clabel)) {
 848  797                          if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
 849  798                              exi)) {
 850  799                                  resp->status = NFS3ERR_ACCES;
 851  800                                  goto out1;
 852  801                          }
 853  802                  }
 854  803          }
 855  804  
 856  805          data = kmem_alloc(MAXPATHLEN + 1, KM_SLEEP);
 857  806  
 858  807          if (is_referral) {
 859  808                  char *s;
 860  809                  size_t strsz;
 861  810  
 862  811                  /* Get an artificial symlink based on a referral */
 863  812                  s = build_symlink(vp, cr, &strsz);
 864  813                  global_svstat_ptr[3][NFS_REFERLINKS].value.ui64++;
 865  814                  DTRACE_PROBE2(nfs3serv__func__referral__reflink,
 866  815                      vnode_t *, vp, char *, s);
 867  816                  if (s == NULL)
 868  817                          error = EINVAL;
 869  818                  else {
 870  819                          error = 0;
 871  820                          (void) strlcpy(data, s, MAXPATHLEN + 1);
 872  821                          kmem_free(s, strsz);
 873  822                  }
 874  823  
 875  824          } else {
 876  825  
 877  826                  iov.iov_base = data;
 878  827                  iov.iov_len = MAXPATHLEN;
 879  828                  uio.uio_iov = &iov;
 880  829                  uio.uio_iovcnt = 1;
 881  830                  uio.uio_segflg = UIO_SYSSPACE;
  
    | ↓ open down ↓ | 47 lines elided | ↑ open up ↑ | 
 882  831                  uio.uio_extflg = UIO_COPY_CACHED;
 883  832                  uio.uio_loffset = 0;
 884  833                  uio.uio_resid = MAXPATHLEN;
 885  834  
 886  835                  error = VOP_READLINK(vp, &uio, cr, NULL);
 887  836  
 888  837                  if (!error)
 889  838                          *(data + MAXPATHLEN - uio.uio_resid) = '\0';
 890  839          }
 891  840  
 892      -#ifdef DEBUG
 893      -        if (rfs3_do_post_op_attr) {
 894      -                va.va_mask = AT_ALL;
 895      -                vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
 896      -        } else
 897      -                vap = NULL;
 898      -#else
 899  841          va.va_mask = AT_ALL;
 900  842          vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
 901      -#endif
      843 +
 902  844          /* Lie about object type again just to be consistent */
 903  845          if (is_referral && vap != NULL)
 904  846                  vap->va_type = VLNK;
 905  847  
 906  848  #if 0 /* notyet */
 907  849          /*
 908  850           * Don't do this.  It causes local disk writes when just
 909  851           * reading the file and the overhead is deemed larger
 910  852           * than the benefit.
 911  853           */
 912  854          /*
 913  855           * Force modified metadata out to stable storage.
 914  856           */
 915  857          (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
 916  858  #endif
 917  859  
 918  860          if (error) {
 919  861                  kmem_free(data, MAXPATHLEN + 1);
 920  862                  goto out;
 921  863          }
 922  864  
 923  865          ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
 924  866          name = nfscmd_convname(ca, exi, data, NFSCMD_CONV_OUTBOUND,
 925  867              MAXPATHLEN + 1);
 926  868  
 927  869          if (name == NULL) {
 928  870                  /*
 929  871                   * Even though the conversion failed, we return
 930  872                   * something. We just don't translate it.
 931  873                   */
 932  874                  name = data;
 933  875          }
 934  876  
 935  877          resp->status = NFS3_OK;
 936  878          vattr_to_post_op_attr(vap, &resp->resok.symlink_attributes);
 937  879          resp->resok.data = name;
 938  880  
 939  881          DTRACE_NFSV3_4(op__readlink__done, struct svc_req *, req,
 940  882              cred_t *, cr, vnode_t *, vp, READLINK3res *, resp);
 941  883          VN_RELE(vp);
 942  884  
 943  885          if (name != data)
 944  886                  kmem_free(data, MAXPATHLEN + 1);
 945  887  
 946  888          return;
 947  889  
 948  890  out:
 949  891          if (curthread->t_flag & T_WOULDBLOCK) {
 950  892                  curthread->t_flag &= ~T_WOULDBLOCK;
 951  893                  resp->status = NFS3ERR_JUKEBOX;
 952  894          } else
 953  895                  resp->status = puterrno3(error);
 954  896  out1:
 955  897          DTRACE_NFSV3_4(op__readlink__done, struct svc_req *, req,
 956  898              cred_t *, cr, vnode_t *, vp, READLINK3res *, resp);
 957  899          if (vp != NULL)
 958  900                  VN_RELE(vp);
 959  901          vattr_to_post_op_attr(vap, &resp->resfail.symlink_attributes);
 960  902  }
 961  903  
 962  904  void *
 963  905  rfs3_readlink_getfh(READLINK3args *args)
 964  906  {
 965  907  
 966  908          return (&args->symlink);
 967  909  }
 968  910  
 969  911  void
 970  912  rfs3_readlink_free(READLINK3res *resp)
 971  913  {
 972  914  
 973  915          if (resp->status == NFS3_OK)
 974  916                  kmem_free(resp->resok.data, MAXPATHLEN + 1);
 975  917  }
 976  918  
 977  919  /*
 978  920   * Server routine to handle read
 979  921   * May handle RDMA data as well as mblks
 980  922   */
 981  923  /* ARGSUSED */
 982  924  void
 983  925  rfs3_read(READ3args *args, READ3res *resp, struct exportinfo *exi,
 984  926          struct svc_req *req, cred_t *cr)
 985  927  {
 986  928          int error;
 987  929          vnode_t *vp;
 988  930          struct vattr *vap;
 989  931          struct vattr va;
 990  932          struct iovec iov;
 991  933          struct uio uio;
 992  934          u_offset_t offset;
 993  935          mblk_t *mp = NULL;
 994  936          int alloc_err = 0;
 995  937          int in_crit = 0;
 996  938          int need_rwunlock = 0;
 997  939          caller_context_t ct;
 998  940          int rdma_used = 0;
 999  941          int loaned_buffers;
1000  942          struct uio *uiop;
1001  943  
1002  944          vap = NULL;
1003  945  
1004  946          vp = nfs3_fhtovp(&args->file, exi);
1005  947  
1006  948          DTRACE_NFSV3_4(op__read__start, struct svc_req *, req,
1007  949              cred_t *, cr, vnode_t *, vp, READ3args *, args);
1008  950  
1009  951          if (vp == NULL) {
1010  952                  error = ESTALE;
1011  953                  goto out;
1012  954          }
1013  955  
1014  956          if (args->wlist) {
1015  957                  if (args->count > clist_len(args->wlist)) {
1016  958                          error = EINVAL;
1017  959                          goto out;
1018  960                  }
1019  961                  rdma_used = 1;
1020  962          }
1021  963  
1022  964          /* use loaned buffers for TCP */
1023  965          loaned_buffers = (nfs_loaned_buffers && !rdma_used) ? 1 : 0;
1024  966  
1025  967          if (is_system_labeled()) {
1026  968                  bslabel_t *clabel = req->rq_label;
1027  969  
1028  970                  ASSERT(clabel != NULL);
1029  971                  DTRACE_PROBE2(tx__rfs3__log__info__opread__clabel, char *,
1030  972                      "got client label from request(1)", struct svc_req *, req);
1031  973  
1032  974                  if (!blequal(&l_admin_low->tsl_label, clabel)) {
1033  975                          if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
1034  976                              exi)) {
1035  977                                  resp->status = NFS3ERR_ACCES;
1036  978                                  goto out1;
1037  979                          }
1038  980                  }
1039  981          }
1040  982  
1041  983          ct.cc_sysid = 0;
1042  984          ct.cc_pid = 0;
1043  985          ct.cc_caller_id = nfs3_srv_caller_id;
1044  986          ct.cc_flags = CC_DONTBLOCK;
1045  987  
1046  988          /*
1047  989           * Enter the critical region before calling VOP_RWLOCK
1048  990           * to avoid a deadlock with write requests.
1049  991           */
1050  992          if (nbl_need_check(vp)) {
1051  993                  nbl_start_crit(vp, RW_READER);
1052  994                  in_crit = 1;
1053  995                  if (nbl_conflict(vp, NBL_READ, args->offset, args->count, 0,
1054  996                      NULL)) {
1055  997                          error = EACCES;
1056  998                          goto out;
1057  999                  }
1058 1000          }
1059 1001  
1060 1002          error = VOP_RWLOCK(vp, V_WRITELOCK_FALSE, &ct);
1061 1003  
1062 1004          /* check if a monitor detected a delegation conflict */
1063 1005          if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
1064 1006                  resp->status = NFS3ERR_JUKEBOX;
1065 1007                  goto out1;
1066 1008          }
1067 1009  
1068 1010          need_rwunlock = 1;
1069 1011  
  
    | ↓ open down ↓ | 158 lines elided | ↑ open up ↑ | 
1070 1012          va.va_mask = AT_ALL;
1071 1013          error = VOP_GETATTR(vp, &va, 0, cr, &ct);
1072 1014  
1073 1015          /*
1074 1016           * If we can't get the attributes, then we can't do the
1075 1017           * right access checking.  So, we'll fail the request.
1076 1018           */
1077 1019          if (error)
1078 1020                  goto out;
1079 1021  
1080      -#ifdef DEBUG
1081      -        if (rfs3_do_post_op_attr)
1082      -                vap = &va;
1083      -#else
1084 1022          vap = &va;
1085      -#endif
1086 1023  
1087 1024          if (vp->v_type != VREG) {
1088 1025                  resp->status = NFS3ERR_INVAL;
1089 1026                  goto out1;
1090 1027          }
1091 1028  
1092 1029          if (crgetuid(cr) != va.va_uid) {
1093 1030                  error = VOP_ACCESS(vp, VREAD, 0, cr, &ct);
1094 1031                  if (error) {
1095 1032                          if (curthread->t_flag & T_WOULDBLOCK)
1096 1033                                  goto out;
1097 1034                          error = VOP_ACCESS(vp, VEXEC, 0, cr, &ct);
1098 1035                          if (error)
1099 1036                                  goto out;
1100 1037                  }
1101 1038          }
1102 1039  
1103 1040          if (MANDLOCK(vp, va.va_mode)) {
1104 1041                  resp->status = NFS3ERR_ACCES;
1105 1042                  goto out1;
1106 1043          }
1107 1044  
1108 1045          offset = args->offset;
1109 1046          if (offset >= va.va_size) {
1110 1047                  VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct);
1111 1048                  if (in_crit)
1112 1049                          nbl_end_crit(vp);
1113 1050                  resp->status = NFS3_OK;
1114 1051                  vattr_to_post_op_attr(vap, &resp->resok.file_attributes);
1115 1052                  resp->resok.count = 0;
1116 1053                  resp->resok.eof = TRUE;
1117 1054                  resp->resok.data.data_len = 0;
1118 1055                  resp->resok.data.data_val = NULL;
1119 1056                  resp->resok.data.mp = NULL;
1120 1057                  /* RDMA */
1121 1058                  resp->resok.wlist = args->wlist;
1122 1059                  resp->resok.wlist_len = resp->resok.count;
1123 1060                  if (resp->resok.wlist)
1124 1061                          clist_zero_len(resp->resok.wlist);
1125 1062                  goto done;
1126 1063          }
1127 1064  
1128 1065          if (args->count == 0) {
1129 1066                  VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct);
1130 1067                  if (in_crit)
1131 1068                          nbl_end_crit(vp);
1132 1069                  resp->status = NFS3_OK;
1133 1070                  vattr_to_post_op_attr(vap, &resp->resok.file_attributes);
1134 1071                  resp->resok.count = 0;
1135 1072                  resp->resok.eof = FALSE;
1136 1073                  resp->resok.data.data_len = 0;
1137 1074                  resp->resok.data.data_val = NULL;
1138 1075                  resp->resok.data.mp = NULL;
1139 1076                  /* RDMA */
1140 1077                  resp->resok.wlist = args->wlist;
1141 1078                  resp->resok.wlist_len = resp->resok.count;
1142 1079                  if (resp->resok.wlist)
1143 1080                          clist_zero_len(resp->resok.wlist);
1144 1081                  goto done;
1145 1082          }
1146 1083  
1147 1084          /*
1148 1085           * do not allocate memory more the max. allowed
1149 1086           * transfer size
1150 1087           */
1151 1088          if (args->count > rfs3_tsize(req))
1152 1089                  args->count = rfs3_tsize(req);
1153 1090  
1154 1091          if (loaned_buffers) {
1155 1092                  uiop = (uio_t *)rfs_setup_xuio(vp);
1156 1093                  ASSERT(uiop != NULL);
1157 1094                  uiop->uio_segflg = UIO_SYSSPACE;
1158 1095                  uiop->uio_loffset = args->offset;
1159 1096                  uiop->uio_resid = args->count;
1160 1097  
1161 1098                  /* Jump to do the read if successful */
1162 1099                  if (VOP_REQZCBUF(vp, UIO_READ, (xuio_t *)uiop, cr, &ct) == 0) {
1163 1100                          /*
1164 1101                           * Need to hold the vnode until after VOP_RETZCBUF()
1165 1102                           * is called.
1166 1103                           */
1167 1104                          VN_HOLD(vp);
1168 1105                          goto doio_read;
1169 1106                  }
1170 1107  
1171 1108                  DTRACE_PROBE2(nfss__i__reqzcbuf_failed, int,
1172 1109                      uiop->uio_loffset, int, uiop->uio_resid);
1173 1110  
1174 1111                  uiop->uio_extflg = 0;
1175 1112                  /* failure to setup for zero copy */
1176 1113                  rfs_free_xuio((void *)uiop);
1177 1114                  loaned_buffers = 0;
1178 1115          }
1179 1116  
1180 1117          /*
1181 1118           * If returning data via RDMA Write, then grab the chunk list.
1182 1119           * If we aren't returning READ data w/RDMA_WRITE, then grab
1183 1120           * a mblk.
1184 1121           */
1185 1122          if (rdma_used) {
1186 1123                  (void) rdma_get_wchunk(req, &iov, args->wlist);
1187 1124          } else {
1188 1125                  /*
1189 1126                   * mp will contain the data to be sent out in the read reply.
1190 1127                   * This will be freed after the reply has been sent out (by the
1191 1128                   * driver).
1192 1129                   * Let's roundup the data to a BYTES_PER_XDR_UNIT multiple, so
1193 1130                   * that the call to xdrmblk_putmblk() never fails.
1194 1131                   */
1195 1132                  mp = allocb_wait(RNDUP(args->count), BPRI_MED, STR_NOSIG,
1196 1133                      &alloc_err);
1197 1134                  ASSERT(mp != NULL);
1198 1135                  ASSERT(alloc_err == 0);
1199 1136  
1200 1137                  iov.iov_base = (caddr_t)mp->b_datap->db_base;
1201 1138                  iov.iov_len = args->count;
1202 1139          }
1203 1140  
1204 1141          uio.uio_iov = &iov;
1205 1142          uio.uio_iovcnt = 1;
1206 1143          uio.uio_segflg = UIO_SYSSPACE;
1207 1144          uio.uio_extflg = UIO_COPY_CACHED;
1208 1145          uio.uio_loffset = args->offset;
1209 1146          uio.uio_resid = args->count;
1210 1147          uiop = &uio;
1211 1148  
1212 1149  doio_read:
1213 1150          error = VOP_READ(vp, uiop, 0, cr, &ct);
1214 1151  
1215 1152          if (error) {
1216 1153                  if (mp)
1217 1154                          freemsg(mp);
1218 1155                  /* check if a monitor detected a delegation conflict */
1219 1156                  if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
1220 1157                          resp->status = NFS3ERR_JUKEBOX;
1221 1158                          goto out1;
1222 1159                  }
1223 1160                  goto out;
1224 1161          }
  
    | ↓ open down ↓ | 129 lines elided | ↑ open up ↑ | 
1225 1162  
1226 1163          /* make mblk using zc buffers */
1227 1164          if (loaned_buffers) {
1228 1165                  mp = uio_to_mblk(uiop);
1229 1166                  ASSERT(mp != NULL);
1230 1167          }
1231 1168  
1232 1169          va.va_mask = AT_ALL;
1233 1170          error = VOP_GETATTR(vp, &va, 0, cr, &ct);
1234 1171  
1235      -#ifdef DEBUG
1236      -        if (rfs3_do_post_op_attr) {
1237      -                if (error)
1238      -                        vap = NULL;
1239      -                else
1240      -                        vap = &va;
1241      -        } else
1242      -                vap = NULL;
1243      -#else
1244 1172          if (error)
1245 1173                  vap = NULL;
1246 1174          else
1247 1175                  vap = &va;
1248      -#endif
1249 1176  
1250 1177          VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct);
1251 1178  
1252 1179          if (in_crit)
1253 1180                  nbl_end_crit(vp);
1254 1181  
1255 1182          resp->status = NFS3_OK;
1256 1183          vattr_to_post_op_attr(vap, &resp->resok.file_attributes);
1257 1184          resp->resok.count = args->count - uiop->uio_resid;
1258 1185          if (!error && offset + resp->resok.count == va.va_size)
1259 1186                  resp->resok.eof = TRUE;
1260 1187          else
1261 1188                  resp->resok.eof = FALSE;
1262 1189          resp->resok.data.data_len = resp->resok.count;
1263 1190  
1264 1191          if (mp)
1265 1192                  rfs_rndup_mblks(mp, resp->resok.count, loaned_buffers);
1266 1193  
1267 1194          resp->resok.data.mp = mp;
1268 1195          resp->resok.size = (uint_t)args->count;
1269 1196  
1270 1197          if (rdma_used) {
1271 1198                  resp->resok.data.data_val = (caddr_t)iov.iov_base;
1272 1199                  if (!rdma_setup_read_data3(args, &(resp->resok))) {
1273 1200                          resp->status = NFS3ERR_INVAL;
1274 1201                  }
1275 1202          } else {
1276 1203                  resp->resok.data.data_val = (caddr_t)mp->b_datap->db_base;
1277 1204                  (resp->resok).wlist = NULL;
1278 1205          }
1279 1206  
1280 1207  done:
1281 1208          DTRACE_NFSV3_4(op__read__done, struct svc_req *, req,
1282 1209              cred_t *, cr, vnode_t *, vp, READ3res *, resp);
1283 1210  
1284 1211          VN_RELE(vp);
1285 1212  
1286 1213          return;
1287 1214  
1288 1215  out:
1289 1216          if (curthread->t_flag & T_WOULDBLOCK) {
1290 1217                  curthread->t_flag &= ~T_WOULDBLOCK;
1291 1218                  resp->status = NFS3ERR_JUKEBOX;
1292 1219          } else
1293 1220                  resp->status = puterrno3(error);
1294 1221  out1:
1295 1222          DTRACE_NFSV3_4(op__read__done, struct svc_req *, req,
1296 1223              cred_t *, cr, vnode_t *, vp, READ3res *, resp);
1297 1224  
1298 1225          if (vp != NULL) {
1299 1226                  if (need_rwunlock)
1300 1227                          VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct);
1301 1228                  if (in_crit)
1302 1229                          nbl_end_crit(vp);
1303 1230                  VN_RELE(vp);
1304 1231          }
1305 1232          vattr_to_post_op_attr(vap, &resp->resfail.file_attributes);
1306 1233  }
1307 1234  
1308 1235  void
1309 1236  rfs3_read_free(READ3res *resp)
1310 1237  {
1311 1238          mblk_t *mp;
1312 1239  
1313 1240          if (resp->status == NFS3_OK) {
1314 1241                  mp = resp->resok.data.mp;
1315 1242                  if (mp != NULL)
1316 1243                          freemsg(mp);
1317 1244          }
1318 1245  }
1319 1246  
1320 1247  void *
1321 1248  rfs3_read_getfh(READ3args *args)
1322 1249  {
1323 1250  
1324 1251          return (&args->file);
1325 1252  }
1326 1253  
1327 1254  #define MAX_IOVECS      12
1328 1255  
1329 1256  #ifdef DEBUG
1330 1257  static int rfs3_write_hits = 0;
1331 1258  static int rfs3_write_misses = 0;
1332 1259  #endif
1333 1260  
1334 1261  void
1335 1262  rfs3_write(WRITE3args *args, WRITE3res *resp, struct exportinfo *exi,
1336 1263          struct svc_req *req, cred_t *cr)
1337 1264  {
1338 1265          int error;
1339 1266          vnode_t *vp;
1340 1267          struct vattr *bvap = NULL;
1341 1268          struct vattr bva;
1342 1269          struct vattr *avap = NULL;
1343 1270          struct vattr ava;
1344 1271          u_offset_t rlimit;
1345 1272          struct uio uio;
1346 1273          struct iovec iov[MAX_IOVECS];
1347 1274          mblk_t *m;
1348 1275          struct iovec *iovp;
1349 1276          int iovcnt;
1350 1277          int ioflag;
1351 1278          cred_t *savecred;
1352 1279          int in_crit = 0;
1353 1280          int rwlock_ret = -1;
1354 1281          caller_context_t ct;
1355 1282  
1356 1283          vp = nfs3_fhtovp(&args->file, exi);
1357 1284  
1358 1285          DTRACE_NFSV3_4(op__write__start, struct svc_req *, req,
1359 1286              cred_t *, cr, vnode_t *, vp, WRITE3args *, args);
1360 1287  
1361 1288          if (vp == NULL) {
1362 1289                  error = ESTALE;
1363 1290                  goto err;
1364 1291          }
1365 1292  
1366 1293          if (is_system_labeled()) {
1367 1294                  bslabel_t *clabel = req->rq_label;
1368 1295  
1369 1296                  ASSERT(clabel != NULL);
1370 1297                  DTRACE_PROBE2(tx__rfs3__log__info__opwrite__clabel, char *,
1371 1298                      "got client label from request(1)", struct svc_req *, req);
1372 1299  
1373 1300                  if (!blequal(&l_admin_low->tsl_label, clabel)) {
1374 1301                          if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
1375 1302                              exi)) {
1376 1303                                  resp->status = NFS3ERR_ACCES;
1377 1304                                  goto err1;
1378 1305                          }
1379 1306                  }
1380 1307          }
1381 1308  
1382 1309          ct.cc_sysid = 0;
1383 1310          ct.cc_pid = 0;
1384 1311          ct.cc_caller_id = nfs3_srv_caller_id;
1385 1312          ct.cc_flags = CC_DONTBLOCK;
1386 1313  
1387 1314          /*
1388 1315           * We have to enter the critical region before calling VOP_RWLOCK
1389 1316           * to avoid a deadlock with ufs.
1390 1317           */
1391 1318          if (nbl_need_check(vp)) {
1392 1319                  nbl_start_crit(vp, RW_READER);
1393 1320                  in_crit = 1;
1394 1321                  if (nbl_conflict(vp, NBL_WRITE, args->offset, args->count, 0,
1395 1322                      NULL)) {
1396 1323                          error = EACCES;
1397 1324                          goto err;
1398 1325                  }
1399 1326          }
1400 1327  
1401 1328          rwlock_ret = VOP_RWLOCK(vp, V_WRITELOCK_TRUE, &ct);
1402 1329  
1403 1330          /* check if a monitor detected a delegation conflict */
1404 1331          if (rwlock_ret == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
1405 1332                  resp->status = NFS3ERR_JUKEBOX;
1406 1333                  rwlock_ret = -1;
1407 1334                  goto err1;
1408 1335          }
1409 1336  
1410 1337  
1411 1338          bva.va_mask = AT_ALL;
  
    | ↓ open down ↓ | 153 lines elided | ↑ open up ↑ | 
1412 1339          error = VOP_GETATTR(vp, &bva, 0, cr, &ct);
1413 1340  
1414 1341          /*
1415 1342           * If we can't get the attributes, then we can't do the
1416 1343           * right access checking.  So, we'll fail the request.
1417 1344           */
1418 1345          if (error)
1419 1346                  goto err;
1420 1347  
1421 1348          bvap = &bva;
1422      -#ifdef DEBUG
1423      -        if (!rfs3_do_pre_op_attr)
1424      -                bvap = NULL;
1425      -#endif
1426 1349          avap = bvap;
1427 1350  
1428 1351          if (args->count != args->data.data_len) {
1429 1352                  resp->status = NFS3ERR_INVAL;
1430 1353                  goto err1;
1431 1354          }
1432 1355  
1433 1356          if (rdonly(exi, req)) {
1434 1357                  resp->status = NFS3ERR_ROFS;
1435 1358                  goto err1;
1436 1359          }
1437 1360  
1438 1361          if (vp->v_type != VREG) {
1439 1362                  resp->status = NFS3ERR_INVAL;
1440 1363                  goto err1;
1441 1364          }
1442 1365  
1443 1366          if (crgetuid(cr) != bva.va_uid &&
1444 1367              (error = VOP_ACCESS(vp, VWRITE, 0, cr, &ct)))
1445 1368                  goto err;
1446 1369  
1447 1370          if (MANDLOCK(vp, bva.va_mode)) {
1448 1371                  resp->status = NFS3ERR_ACCES;
1449 1372                  goto err1;
1450 1373          }
1451 1374  
1452 1375          if (args->count == 0) {
1453 1376                  resp->status = NFS3_OK;
1454 1377                  vattr_to_wcc_data(bvap, avap, &resp->resok.file_wcc);
1455 1378                  resp->resok.count = 0;
1456 1379                  resp->resok.committed = args->stable;
1457 1380                  resp->resok.verf = write3verf;
1458 1381                  goto out;
1459 1382          }
1460 1383  
1461 1384          if (args->mblk != NULL) {
1462 1385                  iovcnt = 0;
1463 1386                  for (m = args->mblk; m != NULL; m = m->b_cont)
1464 1387                          iovcnt++;
1465 1388                  if (iovcnt <= MAX_IOVECS) {
1466 1389  #ifdef DEBUG
1467 1390                          rfs3_write_hits++;
1468 1391  #endif
1469 1392                          iovp = iov;
1470 1393                  } else {
1471 1394  #ifdef DEBUG
1472 1395                          rfs3_write_misses++;
1473 1396  #endif
1474 1397                          iovp = kmem_alloc(sizeof (*iovp) * iovcnt, KM_SLEEP);
1475 1398                  }
1476 1399                  mblk_to_iov(args->mblk, iovcnt, iovp);
1477 1400  
1478 1401          } else if (args->rlist != NULL) {
1479 1402                  iovcnt = 1;
1480 1403                  iovp = iov;
1481 1404                  iovp->iov_base = (char *)((args->rlist)->u.c_daddr3);
1482 1405                  iovp->iov_len = args->count;
1483 1406          } else {
1484 1407                  iovcnt = 1;
1485 1408                  iovp = iov;
1486 1409                  iovp->iov_base = args->data.data_val;
1487 1410                  iovp->iov_len = args->count;
1488 1411          }
1489 1412  
1490 1413          uio.uio_iov = iovp;
1491 1414          uio.uio_iovcnt = iovcnt;
1492 1415  
1493 1416          uio.uio_segflg = UIO_SYSSPACE;
1494 1417          uio.uio_extflg = UIO_COPY_DEFAULT;
1495 1418          uio.uio_loffset = args->offset;
1496 1419          uio.uio_resid = args->count;
1497 1420          uio.uio_llimit = curproc->p_fsz_ctl;
1498 1421          rlimit = uio.uio_llimit - args->offset;
1499 1422          if (rlimit < (u_offset_t)uio.uio_resid)
1500 1423                  uio.uio_resid = (int)rlimit;
1501 1424  
1502 1425          if (args->stable == UNSTABLE)
1503 1426                  ioflag = 0;
1504 1427          else if (args->stable == FILE_SYNC)
1505 1428                  ioflag = FSYNC;
1506 1429          else if (args->stable == DATA_SYNC)
1507 1430                  ioflag = FDSYNC;
1508 1431          else {
1509 1432                  if (iovp != iov)
1510 1433                          kmem_free(iovp, sizeof (*iovp) * iovcnt);
1511 1434                  resp->status = NFS3ERR_INVAL;
1512 1435                  goto err1;
1513 1436          }
1514 1437  
1515 1438          /*
1516 1439           * We're changing creds because VM may fault and we need
1517 1440           * the cred of the current thread to be used if quota
1518 1441           * checking is enabled.
1519 1442           */
1520 1443          savecred = curthread->t_cred;
1521 1444          curthread->t_cred = cr;
1522 1445          error = VOP_WRITE(vp, &uio, ioflag, cr, &ct);
1523 1446          curthread->t_cred = savecred;
1524 1447  
1525 1448          if (iovp != iov)
1526 1449                  kmem_free(iovp, sizeof (*iovp) * iovcnt);
  
    | ↓ open down ↓ | 91 lines elided | ↑ open up ↑ | 
1527 1450  
1528 1451          /* check if a monitor detected a delegation conflict */
1529 1452          if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
1530 1453                  resp->status = NFS3ERR_JUKEBOX;
1531 1454                  goto err1;
1532 1455          }
1533 1456  
1534 1457          ava.va_mask = AT_ALL;
1535 1458          avap = VOP_GETATTR(vp, &ava, 0, cr, &ct) ? NULL : &ava;
1536 1459  
1537      -#ifdef DEBUG
1538      -        if (!rfs3_do_post_op_attr)
1539      -                avap = NULL;
1540      -#endif
1541      -
1542 1460          if (error)
1543 1461                  goto err;
1544 1462  
1545 1463          /*
1546 1464           * If we were unable to get the V_WRITELOCK_TRUE, then we
1547 1465           * may not have accurate after attrs, so check if
1548 1466           * we have both attributes, they have a non-zero va_seq, and
1549 1467           * va_seq has changed by exactly one,
1550 1468           * if not, turn off the before attr.
1551 1469           */
1552 1470          if (rwlock_ret != V_WRITELOCK_TRUE) {
1553 1471                  if (bvap == NULL || avap == NULL ||
1554 1472                      bvap->va_seq == 0 || avap->va_seq == 0 ||
1555 1473                      avap->va_seq != (bvap->va_seq + 1)) {
1556 1474                          bvap = NULL;
1557 1475                  }
1558 1476          }
1559 1477  
1560 1478          resp->status = NFS3_OK;
1561 1479          vattr_to_wcc_data(bvap, avap, &resp->resok.file_wcc);
1562 1480          resp->resok.count = args->count - uio.uio_resid;
1563 1481          resp->resok.committed = args->stable;
1564 1482          resp->resok.verf = write3verf;
1565 1483          goto out;
1566 1484  
1567 1485  err:
1568 1486          if (curthread->t_flag & T_WOULDBLOCK) {
1569 1487                  curthread->t_flag &= ~T_WOULDBLOCK;
1570 1488                  resp->status = NFS3ERR_JUKEBOX;
1571 1489          } else
1572 1490                  resp->status = puterrno3(error);
1573 1491  err1:
1574 1492          vattr_to_wcc_data(bvap, avap, &resp->resfail.file_wcc);
1575 1493  out:
1576 1494          DTRACE_NFSV3_4(op__write__done, struct svc_req *, req,
1577 1495              cred_t *, cr, vnode_t *, vp, WRITE3res *, resp);
1578 1496  
1579 1497          if (vp != NULL) {
1580 1498                  if (rwlock_ret != -1)
1581 1499                          VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, &ct);
1582 1500                  if (in_crit)
1583 1501                          nbl_end_crit(vp);
1584 1502                  VN_RELE(vp);
1585 1503          }
1586 1504  }
1587 1505  
1588 1506  void *
1589 1507  rfs3_write_getfh(WRITE3args *args)
1590 1508  {
1591 1509  
1592 1510          return (&args->file);
1593 1511  }
1594 1512  
1595 1513  void
1596 1514  rfs3_create(CREATE3args *args, CREATE3res *resp, struct exportinfo *exi,
1597 1515          struct svc_req *req, cred_t *cr)
1598 1516  {
1599 1517          int error;
1600 1518          int in_crit = 0;
1601 1519          vnode_t *vp;
1602 1520          vnode_t *tvp = NULL;
1603 1521          vnode_t *dvp;
1604 1522          struct vattr *vap;
1605 1523          struct vattr va;
1606 1524          struct vattr *dbvap;
1607 1525          struct vattr dbva;
1608 1526          struct vattr *davap;
1609 1527          struct vattr dava;
1610 1528          enum vcexcl excl;
1611 1529          nfstime3 *mtime;
1612 1530          len_t reqsize;
1613 1531          bool_t trunc;
1614 1532          struct sockaddr *ca;
1615 1533          char *name = NULL;
1616 1534  
1617 1535          dbvap = NULL;
1618 1536          davap = NULL;
1619 1537  
  
    | ↓ open down ↓ | 68 lines elided | ↑ open up ↑ | 
1620 1538          dvp = nfs3_fhtovp(&args->where.dir, exi);
1621 1539  
1622 1540          DTRACE_NFSV3_4(op__create__start, struct svc_req *, req,
1623 1541              cred_t *, cr, vnode_t *, dvp, CREATE3args *, args);
1624 1542  
1625 1543          if (dvp == NULL) {
1626 1544                  error = ESTALE;
1627 1545                  goto out;
1628 1546          }
1629 1547  
1630      -#ifdef DEBUG
1631      -        if (rfs3_do_pre_op_attr) {
1632      -                dbva.va_mask = AT_ALL;
1633      -                dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
1634      -        } else
1635      -                dbvap = NULL;
1636      -#else
1637 1548          dbva.va_mask = AT_ALL;
1638 1549          dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
1639      -#endif
1640 1550          davap = dbvap;
1641 1551  
1642 1552          if (args->where.name == nfs3nametoolong) {
1643 1553                  resp->status = NFS3ERR_NAMETOOLONG;
1644 1554                  goto out1;
1645 1555          }
1646 1556  
1647 1557          if (args->where.name == NULL || *(args->where.name) == '\0') {
1648 1558                  resp->status = NFS3ERR_ACCES;
1649 1559                  goto out1;
1650 1560          }
1651 1561  
1652 1562          if (rdonly(exi, req)) {
1653 1563                  resp->status = NFS3ERR_ROFS;
1654 1564                  goto out1;
1655 1565          }
1656 1566  
1657 1567          if (is_system_labeled()) {
1658 1568                  bslabel_t *clabel = req->rq_label;
1659 1569  
1660 1570                  ASSERT(clabel != NULL);
1661 1571                  DTRACE_PROBE2(tx__rfs3__log__info__opcreate__clabel, char *,
1662 1572                      "got client label from request(1)", struct svc_req *, req);
1663 1573  
1664 1574                  if (!blequal(&l_admin_low->tsl_label, clabel)) {
1665 1575                          if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK,
1666 1576                              exi)) {
1667 1577                                  resp->status = NFS3ERR_ACCES;
1668 1578                                  goto out1;
1669 1579                          }
1670 1580                  }
1671 1581          }
1672 1582  
1673 1583          ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
1674 1584          name = nfscmd_convname(ca, exi, args->where.name,
1675 1585              NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
1676 1586  
1677 1587          if (name == NULL) {
1678 1588                  /* This is really a Solaris EILSEQ */
1679 1589                  resp->status = NFS3ERR_INVAL;
1680 1590                  goto out1;
1681 1591          }
1682 1592  
1683 1593          if (args->how.mode == EXCLUSIVE) {
1684 1594                  va.va_mask = AT_TYPE | AT_MODE | AT_MTIME;
1685 1595                  va.va_type = VREG;
1686 1596                  va.va_mode = (mode_t)0;
1687 1597                  /*
1688 1598                   * Ensure no time overflows and that types match
1689 1599                   */
1690 1600                  mtime = (nfstime3 *)&args->how.createhow3_u.verf;
1691 1601                  va.va_mtime.tv_sec = mtime->seconds % INT32_MAX;
1692 1602                  va.va_mtime.tv_nsec = mtime->nseconds;
1693 1603                  excl = EXCL;
1694 1604          } else {
1695 1605                  error = sattr3_to_vattr(&args->how.createhow3_u.obj_attributes,
1696 1606                      &va);
1697 1607                  if (error)
1698 1608                          goto out;
1699 1609                  va.va_mask |= AT_TYPE;
1700 1610                  va.va_type = VREG;
1701 1611                  if (args->how.mode == GUARDED)
1702 1612                          excl = EXCL;
1703 1613                  else {
1704 1614                          excl = NONEXCL;
1705 1615  
1706 1616                          /*
1707 1617                           * During creation of file in non-exclusive mode
1708 1618                           * if size of file is being set then make sure
1709 1619                           * that if the file already exists that no conflicting
1710 1620                           * non-blocking mandatory locks exists in the region
1711 1621                           * being modified. If there are conflicting locks fail
1712 1622                           * the operation with EACCES.
1713 1623                           */
1714 1624                          if (va.va_mask & AT_SIZE) {
1715 1625                                  struct vattr tva;
1716 1626  
1717 1627                                  /*
1718 1628                                   * Does file already exist?
1719 1629                                   */
1720 1630                                  error = VOP_LOOKUP(dvp, name, &tvp,
1721 1631                                      NULL, 0, NULL, cr, NULL, NULL, NULL);
1722 1632  
1723 1633                                  /*
1724 1634                                   * Check to see if the file has been delegated
1725 1635                                   * to a v4 client.  If so, then begin recall of
1726 1636                                   * the delegation and return JUKEBOX to allow
1727 1637                                   * the client to retrasmit its request.
1728 1638                                   */
1729 1639  
1730 1640                                  trunc = va.va_size == 0;
1731 1641                                  if (!error &&
1732 1642                                      rfs4_check_delegated(FWRITE, tvp, trunc)) {
1733 1643                                          resp->status = NFS3ERR_JUKEBOX;
1734 1644                                          goto out1;
1735 1645                                  }
1736 1646  
1737 1647                                  /*
1738 1648                                   * Check for NBMAND lock conflicts
1739 1649                                   */
1740 1650                                  if (!error && nbl_need_check(tvp)) {
1741 1651                                          u_offset_t offset;
1742 1652                                          ssize_t len;
1743 1653  
1744 1654                                          nbl_start_crit(tvp, RW_READER);
1745 1655                                          in_crit = 1;
1746 1656  
1747 1657                                          tva.va_mask = AT_SIZE;
1748 1658                                          error = VOP_GETATTR(tvp, &tva, 0, cr,
1749 1659                                              NULL);
1750 1660                                          /*
1751 1661                                           * Can't check for conflicts, so return
1752 1662                                           * error.
1753 1663                                           */
1754 1664                                          if (error)
1755 1665                                                  goto out;
1756 1666  
1757 1667                                          offset = tva.va_size < va.va_size ?
1758 1668                                              tva.va_size : va.va_size;
1759 1669                                          len = tva.va_size < va.va_size ?
1760 1670                                              va.va_size - tva.va_size :
1761 1671                                              tva.va_size - va.va_size;
1762 1672                                          if (nbl_conflict(tvp, NBL_WRITE,
1763 1673                                              offset, len, 0, NULL)) {
1764 1674                                                  error = EACCES;
1765 1675                                                  goto out;
1766 1676                                          }
1767 1677                                  } else if (tvp) {
1768 1678                                          VN_RELE(tvp);
1769 1679                                          tvp = NULL;
1770 1680                                  }
1771 1681                          }
1772 1682                  }
1773 1683                  if (va.va_mask & AT_SIZE)
1774 1684                          reqsize = va.va_size;
1775 1685          }
1776 1686  
1777 1687          /*
1778 1688           * Must specify the mode.
1779 1689           */
1780 1690          if (!(va.va_mask & AT_MODE)) {
1781 1691                  resp->status = NFS3ERR_INVAL;
1782 1692                  goto out1;
1783 1693          }
1784 1694  
1785 1695          /*
1786 1696           * If the filesystem is exported with nosuid, then mask off
1787 1697           * the setuid and setgid bits.
1788 1698           */
1789 1699          if (va.va_type == VREG && (exi->exi_export.ex_flags & EX_NOSUID))
1790 1700                  va.va_mode &= ~(VSUID | VSGID);
1791 1701  
  
    | ↓ open down ↓ | 142 lines elided | ↑ open up ↑ | 
1792 1702  tryagain:
1793 1703          /*
1794 1704           * The file open mode used is VWRITE.  If the client needs
1795 1705           * some other semantic, then it should do the access checking
1796 1706           * itself.  It would have been nice to have the file open mode
1797 1707           * passed as part of the arguments.
1798 1708           */
1799 1709          error = VOP_CREATE(dvp, name, &va, excl, VWRITE,
1800 1710              &vp, cr, 0, NULL, NULL);
1801 1711  
1802      -#ifdef DEBUG
1803      -        if (rfs3_do_post_op_attr) {
1804      -                dava.va_mask = AT_ALL;
1805      -                davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
1806      -        } else
1807      -                davap = NULL;
1808      -#else
1809 1712          dava.va_mask = AT_ALL;
1810 1713          davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
1811      -#endif
1812 1714  
1813 1715          if (error) {
1814 1716                  /*
1815 1717                   * If we got something other than file already exists
1816 1718                   * then just return this error.  Otherwise, we got
1817 1719                   * EEXIST.  If we were doing a GUARDED create, then
1818 1720                   * just return this error.  Otherwise, we need to
1819 1721                   * make sure that this wasn't a duplicate of an
1820 1722                   * exclusive create request.
1821 1723                   *
1822 1724                   * The assumption is made that a non-exclusive create
1823 1725                   * request will never return EEXIST.
1824 1726                   */
1825 1727                  if (error != EEXIST || args->how.mode == GUARDED)
1826 1728                          goto out;
1827 1729                  /*
1828 1730                   * Lookup the file so that we can get a vnode for it.
1829 1731                   */
1830 1732                  error = VOP_LOOKUP(dvp, name, &vp, NULL, 0,
1831 1733                      NULL, cr, NULL, NULL, NULL);
1832 1734                  if (error) {
1833 1735                          /*
1834 1736                           * We couldn't find the file that we thought that
1835 1737                           * we just created.  So, we'll just try creating
1836 1738                           * it again.
1837 1739                           */
1838 1740                          if (error == ENOENT)
1839 1741                                  goto tryagain;
1840 1742                          goto out;
1841 1743                  }
1842 1744  
1843 1745                  /*
1844 1746                   * If the file is delegated to a v4 client, go ahead
1845 1747                   * and initiate recall, this create is a hint that a
1846 1748                   * conflicting v3 open has occurred.
1847 1749                   */
1848 1750  
1849 1751                  if (rfs4_check_delegated(FWRITE, vp, FALSE)) {
1850 1752                          VN_RELE(vp);
1851 1753                          resp->status = NFS3ERR_JUKEBOX;
1852 1754                          goto out1;
1853 1755                  }
1854 1756  
1855 1757                  va.va_mask = AT_ALL;
1856 1758                  vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
1857 1759  
1858 1760                  mtime = (nfstime3 *)&args->how.createhow3_u.verf;
1859 1761                  /* % with INT32_MAX to prevent overflows */
1860 1762                  if (args->how.mode == EXCLUSIVE && (vap == NULL ||
1861 1763                      vap->va_mtime.tv_sec !=
1862 1764                      (mtime->seconds % INT32_MAX) ||
1863 1765                      vap->va_mtime.tv_nsec != mtime->nseconds)) {
1864 1766                          VN_RELE(vp);
1865 1767                          error = EEXIST;
1866 1768                          goto out;
1867 1769                  }
1868 1770          } else {
1869 1771  
1870 1772                  if ((args->how.mode == UNCHECKED ||
1871 1773                      args->how.mode == GUARDED) &&
1872 1774                      args->how.createhow3_u.obj_attributes.size.set_it &&
1873 1775                      va.va_size == 0)
1874 1776                          trunc = TRUE;
1875 1777                  else
1876 1778                          trunc = FALSE;
1877 1779  
1878 1780                  if (rfs4_check_delegated(FWRITE, vp, trunc)) {
1879 1781                          VN_RELE(vp);
1880 1782                          resp->status = NFS3ERR_JUKEBOX;
1881 1783                          goto out1;
1882 1784                  }
1883 1785  
1884 1786                  va.va_mask = AT_ALL;
1885 1787                  vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
1886 1788  
1887 1789                  /*
1888 1790                   * We need to check to make sure that the file got
1889 1791                   * created to the indicated size.  If not, we do a
1890 1792                   * setattr to try to change the size, but we don't
1891 1793                   * try too hard.  This shouldn't a problem as most
1892 1794                   * clients will only specifiy a size of zero which
1893 1795                   * local file systems handle.  However, even if
1894 1796                   * the client does specify a non-zero size, it can
1895 1797                   * still recover by checking the size of the file
1896 1798                   * after it has created it and then issue a setattr
1897 1799                   * request of its own to set the size of the file.
1898 1800                   */
1899 1801                  if (vap != NULL &&
1900 1802                      (args->how.mode == UNCHECKED ||
1901 1803                      args->how.mode == GUARDED) &&
1902 1804                      args->how.createhow3_u.obj_attributes.size.set_it &&
1903 1805                      vap->va_size != reqsize) {
1904 1806                          va.va_mask = AT_SIZE;
  
    | ↓ open down ↓ | 83 lines elided | ↑ open up ↑ | 
1905 1807                          va.va_size = reqsize;
1906 1808                          (void) VOP_SETATTR(vp, &va, 0, cr, NULL);
1907 1809                          va.va_mask = AT_ALL;
1908 1810                          vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
1909 1811                  }
1910 1812          }
1911 1813  
1912 1814          if (name != args->where.name)
1913 1815                  kmem_free(name, MAXPATHLEN + 1);
1914 1816  
1915      -#ifdef DEBUG
1916      -        if (!rfs3_do_post_op_attr)
1917      -                vap = NULL;
1918      -#endif
1919      -
1920      -#ifdef DEBUG
1921      -        if (!rfs3_do_post_op_fh3)
1922      -                resp->resok.obj.handle_follows = FALSE;
1923      -        else {
1924      -#endif
1925 1817          error = makefh3(&resp->resok.obj.handle, vp, exi);
1926 1818          if (error)
1927 1819                  resp->resok.obj.handle_follows = FALSE;
1928 1820          else
1929 1821                  resp->resok.obj.handle_follows = TRUE;
1930      -#ifdef DEBUG
1931      -        }
1932      -#endif
1933 1822  
1934 1823          /*
1935 1824           * Force modified data and metadata out to stable storage.
1936 1825           */
1937 1826          (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
1938 1827          (void) VOP_FSYNC(dvp, 0, cr, NULL);
1939 1828  
1940 1829          VN_RELE(vp);
1941 1830          if (tvp != NULL) {
1942 1831                  if (in_crit)
1943 1832                          nbl_end_crit(tvp);
1944 1833                  VN_RELE(tvp);
1945 1834          }
1946 1835  
1947 1836          resp->status = NFS3_OK;
1948 1837          vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
1949 1838          vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
1950 1839  
1951 1840          DTRACE_NFSV3_4(op__create__done, struct svc_req *, req,
1952 1841              cred_t *, cr, vnode_t *, dvp, CREATE3res *, resp);
1953 1842  
1954 1843          VN_RELE(dvp);
1955 1844          return;
1956 1845  
1957 1846  out:
1958 1847          if (curthread->t_flag & T_WOULDBLOCK) {
1959 1848                  curthread->t_flag &= ~T_WOULDBLOCK;
1960 1849                  resp->status = NFS3ERR_JUKEBOX;
1961 1850          } else
1962 1851                  resp->status = puterrno3(error);
1963 1852  out1:
1964 1853          DTRACE_NFSV3_4(op__create__done, struct svc_req *, req,
1965 1854              cred_t *, cr, vnode_t *, dvp, CREATE3res *, resp);
1966 1855  
1967 1856          if (name != NULL && name != args->where.name)
1968 1857                  kmem_free(name, MAXPATHLEN + 1);
1969 1858  
1970 1859          if (tvp != NULL) {
1971 1860                  if (in_crit)
1972 1861                          nbl_end_crit(tvp);
1973 1862                  VN_RELE(tvp);
1974 1863          }
1975 1864          if (dvp != NULL)
1976 1865                  VN_RELE(dvp);
1977 1866          vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
1978 1867  }
1979 1868  
1980 1869  void *
1981 1870  rfs3_create_getfh(CREATE3args *args)
1982 1871  {
1983 1872  
1984 1873          return (&args->where.dir);
1985 1874  }
1986 1875  
1987 1876  void
1988 1877  rfs3_mkdir(MKDIR3args *args, MKDIR3res *resp, struct exportinfo *exi,
1989 1878          struct svc_req *req, cred_t *cr)
1990 1879  {
1991 1880          int error;
1992 1881          vnode_t *vp = NULL;
1993 1882          vnode_t *dvp;
1994 1883          struct vattr *vap;
1995 1884          struct vattr va;
1996 1885          struct vattr *dbvap;
1997 1886          struct vattr dbva;
1998 1887          struct vattr *davap;
1999 1888          struct vattr dava;
2000 1889          struct sockaddr *ca;
2001 1890          char *name = NULL;
2002 1891  
2003 1892          dbvap = NULL;
2004 1893          davap = NULL;
2005 1894  
  
    | ↓ open down ↓ | 63 lines elided | ↑ open up ↑ | 
2006 1895          dvp = nfs3_fhtovp(&args->where.dir, exi);
2007 1896  
2008 1897          DTRACE_NFSV3_4(op__mkdir__start, struct svc_req *, req,
2009 1898              cred_t *, cr, vnode_t *, dvp, MKDIR3args *, args);
2010 1899  
2011 1900          if (dvp == NULL) {
2012 1901                  error = ESTALE;
2013 1902                  goto out;
2014 1903          }
2015 1904  
2016      -#ifdef DEBUG
2017      -        if (rfs3_do_pre_op_attr) {
2018      -                dbva.va_mask = AT_ALL;
2019      -                dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
2020      -        } else
2021      -                dbvap = NULL;
2022      -#else
2023 1905          dbva.va_mask = AT_ALL;
2024 1906          dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
2025      -#endif
2026 1907          davap = dbvap;
2027 1908  
2028 1909          if (args->where.name == nfs3nametoolong) {
2029 1910                  resp->status = NFS3ERR_NAMETOOLONG;
2030 1911                  goto out1;
2031 1912          }
2032 1913  
2033 1914          if (args->where.name == NULL || *(args->where.name) == '\0') {
2034 1915                  resp->status = NFS3ERR_ACCES;
2035 1916                  goto out1;
2036 1917          }
2037 1918  
2038 1919          if (rdonly(exi, req)) {
2039 1920                  resp->status = NFS3ERR_ROFS;
2040 1921                  goto out1;
2041 1922          }
2042 1923  
2043 1924          if (is_system_labeled()) {
2044 1925                  bslabel_t *clabel = req->rq_label;
2045 1926  
2046 1927                  ASSERT(clabel != NULL);
2047 1928                  DTRACE_PROBE2(tx__rfs3__log__info__opmkdir__clabel, char *,
2048 1929                      "got client label from request(1)", struct svc_req *, req);
2049 1930  
2050 1931                  if (!blequal(&l_admin_low->tsl_label, clabel)) {
2051 1932                          if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK,
2052 1933                              exi)) {
2053 1934                                  resp->status = NFS3ERR_ACCES;
2054 1935                                  goto out1;
2055 1936                          }
2056 1937                  }
2057 1938          }
2058 1939  
2059 1940          error = sattr3_to_vattr(&args->attributes, &va);
2060 1941          if (error)
2061 1942                  goto out;
2062 1943  
2063 1944          if (!(va.va_mask & AT_MODE)) {
2064 1945                  resp->status = NFS3ERR_INVAL;
2065 1946                  goto out1;
2066 1947          }
2067 1948  
2068 1949          ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2069 1950          name = nfscmd_convname(ca, exi, args->where.name,
2070 1951              NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2071 1952  
2072 1953          if (name == NULL) {
2073 1954                  resp->status = NFS3ERR_INVAL;
2074 1955                  goto out1;
  
    | ↓ open down ↓ | 39 lines elided | ↑ open up ↑ | 
2075 1956          }
2076 1957  
2077 1958          va.va_mask |= AT_TYPE;
2078 1959          va.va_type = VDIR;
2079 1960  
2080 1961          error = VOP_MKDIR(dvp, name, &va, &vp, cr, NULL, 0, NULL);
2081 1962  
2082 1963          if (name != args->where.name)
2083 1964                  kmem_free(name, MAXPATHLEN + 1);
2084 1965  
2085      -#ifdef DEBUG
2086      -        if (rfs3_do_post_op_attr) {
2087      -                dava.va_mask = AT_ALL;
2088      -                davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
2089      -        } else
2090      -                davap = NULL;
2091      -#else
2092 1966          dava.va_mask = AT_ALL;
2093 1967          davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
2094      -#endif
2095 1968  
2096 1969          /*
2097 1970           * Force modified data and metadata out to stable storage.
2098 1971           */
2099 1972          (void) VOP_FSYNC(dvp, 0, cr, NULL);
2100 1973  
2101 1974          if (error)
2102 1975                  goto out;
2103 1976  
2104      -#ifdef DEBUG
2105      -        if (!rfs3_do_post_op_fh3)
2106      -                resp->resok.obj.handle_follows = FALSE;
2107      -        else {
2108      -#endif
2109 1977          error = makefh3(&resp->resok.obj.handle, vp, exi);
2110 1978          if (error)
2111 1979                  resp->resok.obj.handle_follows = FALSE;
2112 1980          else
2113 1981                  resp->resok.obj.handle_follows = TRUE;
2114      -#ifdef DEBUG
2115      -        }
2116      -#endif
2117 1982  
2118      -#ifdef DEBUG
2119      -        if (rfs3_do_post_op_attr) {
2120      -                va.va_mask = AT_ALL;
2121      -                vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
2122      -        } else
2123      -                vap = NULL;
2124      -#else
2125 1983          va.va_mask = AT_ALL;
2126 1984          vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
2127      -#endif
2128 1985  
2129 1986          /*
2130 1987           * Force modified data and metadata out to stable storage.
2131 1988           */
2132 1989          (void) VOP_FSYNC(vp, 0, cr, NULL);
2133 1990  
2134 1991          VN_RELE(vp);
2135 1992  
2136 1993          resp->status = NFS3_OK;
2137 1994          vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
2138 1995          vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
2139 1996  
2140 1997          DTRACE_NFSV3_4(op__mkdir__done, struct svc_req *, req,
2141 1998              cred_t *, cr, vnode_t *, dvp, MKDIR3res *, resp);
2142 1999          VN_RELE(dvp);
2143 2000  
2144 2001          return;
2145 2002  
2146 2003  out:
2147 2004          if (curthread->t_flag & T_WOULDBLOCK) {
2148 2005                  curthread->t_flag &= ~T_WOULDBLOCK;
2149 2006                  resp->status = NFS3ERR_JUKEBOX;
2150 2007          } else
2151 2008                  resp->status = puterrno3(error);
2152 2009  out1:
2153 2010          DTRACE_NFSV3_4(op__mkdir__done, struct svc_req *, req,
2154 2011              cred_t *, cr, vnode_t *, dvp, MKDIR3res *, resp);
2155 2012          if (dvp != NULL)
2156 2013                  VN_RELE(dvp);
2157 2014          vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
2158 2015  }
2159 2016  
2160 2017  void *
2161 2018  rfs3_mkdir_getfh(MKDIR3args *args)
2162 2019  {
2163 2020  
2164 2021          return (&args->where.dir);
2165 2022  }
2166 2023  
2167 2024  void
2168 2025  rfs3_symlink(SYMLINK3args *args, SYMLINK3res *resp, struct exportinfo *exi,
2169 2026          struct svc_req *req, cred_t *cr)
2170 2027  {
2171 2028          int error;
2172 2029          vnode_t *vp;
2173 2030          vnode_t *dvp;
2174 2031          struct vattr *vap;
2175 2032          struct vattr va;
2176 2033          struct vattr *dbvap;
2177 2034          struct vattr dbva;
2178 2035          struct vattr *davap;
2179 2036          struct vattr dava;
2180 2037          struct sockaddr *ca;
2181 2038          char *name = NULL;
2182 2039          char *symdata = NULL;
2183 2040  
2184 2041          dbvap = NULL;
2185 2042          davap = NULL;
2186 2043  
  
    | ↓ open down ↓ | 49 lines elided | ↑ open up ↑ | 
2187 2044          dvp = nfs3_fhtovp(&args->where.dir, exi);
2188 2045  
2189 2046          DTRACE_NFSV3_4(op__symlink__start, struct svc_req *, req,
2190 2047              cred_t *, cr, vnode_t *, dvp, SYMLINK3args *, args);
2191 2048  
2192 2049          if (dvp == NULL) {
2193 2050                  error = ESTALE;
2194 2051                  goto err;
2195 2052          }
2196 2053  
2197      -#ifdef DEBUG
2198      -        if (rfs3_do_pre_op_attr) {
2199      -                dbva.va_mask = AT_ALL;
2200      -                dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
2201      -        } else
2202      -                dbvap = NULL;
2203      -#else
2204 2054          dbva.va_mask = AT_ALL;
2205 2055          dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
2206      -#endif
2207 2056          davap = dbvap;
2208 2057  
2209 2058          if (args->where.name == nfs3nametoolong) {
2210 2059                  resp->status = NFS3ERR_NAMETOOLONG;
2211 2060                  goto err1;
2212 2061          }
2213 2062  
2214 2063          if (args->where.name == NULL || *(args->where.name) == '\0') {
2215 2064                  resp->status = NFS3ERR_ACCES;
2216 2065                  goto err1;
2217 2066          }
2218 2067  
2219 2068          if (rdonly(exi, req)) {
2220 2069                  resp->status = NFS3ERR_ROFS;
2221 2070                  goto err1;
2222 2071          }
2223 2072  
2224 2073          if (is_system_labeled()) {
2225 2074                  bslabel_t *clabel = req->rq_label;
2226 2075  
2227 2076                  ASSERT(clabel != NULL);
2228 2077                  DTRACE_PROBE2(tx__rfs3__log__info__opsymlink__clabel, char *,
2229 2078                      "got client label from request(1)", struct svc_req *, req);
2230 2079  
2231 2080                  if (!blequal(&l_admin_low->tsl_label, clabel)) {
2232 2081                          if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK,
2233 2082                              exi)) {
2234 2083                                  resp->status = NFS3ERR_ACCES;
2235 2084                                  goto err1;
2236 2085                          }
2237 2086                  }
2238 2087          }
2239 2088  
2240 2089          error = sattr3_to_vattr(&args->symlink.symlink_attributes, &va);
2241 2090          if (error)
2242 2091                  goto err;
2243 2092  
2244 2093          if (!(va.va_mask & AT_MODE)) {
2245 2094                  resp->status = NFS3ERR_INVAL;
2246 2095                  goto err1;
2247 2096          }
2248 2097  
2249 2098          if (args->symlink.symlink_data == nfs3nametoolong) {
2250 2099                  resp->status = NFS3ERR_NAMETOOLONG;
2251 2100                  goto err1;
2252 2101          }
2253 2102  
2254 2103          ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2255 2104          name = nfscmd_convname(ca, exi, args->where.name,
2256 2105              NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2257 2106  
2258 2107          if (name == NULL) {
2259 2108                  /* This is really a Solaris EILSEQ */
2260 2109                  resp->status = NFS3ERR_INVAL;
2261 2110                  goto err1;
2262 2111          }
2263 2112  
2264 2113          symdata = nfscmd_convname(ca, exi, args->symlink.symlink_data,
2265 2114              NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2266 2115          if (symdata == NULL) {
2267 2116                  /* This is really a Solaris EILSEQ */
  
    | ↓ open down ↓ | 51 lines elided | ↑ open up ↑ | 
2268 2117                  resp->status = NFS3ERR_INVAL;
2269 2118                  goto err1;
2270 2119          }
2271 2120  
2272 2121  
2273 2122          va.va_mask |= AT_TYPE;
2274 2123          va.va_type = VLNK;
2275 2124  
2276 2125          error = VOP_SYMLINK(dvp, name, &va, symdata, cr, NULL, 0);
2277 2126  
2278      -#ifdef DEBUG
2279      -        if (rfs3_do_post_op_attr) {
2280      -                dava.va_mask = AT_ALL;
2281      -                davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
2282      -        } else
2283      -                davap = NULL;
2284      -#else
2285 2127          dava.va_mask = AT_ALL;
2286 2128          davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
2287      -#endif
2288 2129  
2289 2130          if (error)
2290 2131                  goto err;
2291 2132  
2292 2133          error = VOP_LOOKUP(dvp, name, &vp, NULL, 0, NULL, cr,
2293 2134              NULL, NULL, NULL);
2294 2135  
2295 2136          /*
2296 2137           * Force modified data and metadata out to stable storage.
2297 2138           */
2298 2139          (void) VOP_FSYNC(dvp, 0, cr, NULL);
  
    | ↓ open down ↓ | 1 lines elided | ↑ open up ↑ | 
2299 2140  
2300 2141  
2301 2142          resp->status = NFS3_OK;
2302 2143          if (error) {
2303 2144                  resp->resok.obj.handle_follows = FALSE;
2304 2145                  vattr_to_post_op_attr(NULL, &resp->resok.obj_attributes);
2305 2146                  vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
2306 2147                  goto out;
2307 2148          }
2308 2149  
2309      -#ifdef DEBUG
2310      -        if (!rfs3_do_post_op_fh3)
2311      -                resp->resok.obj.handle_follows = FALSE;
2312      -        else {
2313      -#endif
2314 2150          error = makefh3(&resp->resok.obj.handle, vp, exi);
2315 2151          if (error)
2316 2152                  resp->resok.obj.handle_follows = FALSE;
2317 2153          else
2318 2154                  resp->resok.obj.handle_follows = TRUE;
2319      -#ifdef DEBUG
2320      -        }
2321      -#endif
2322 2155  
2323      -#ifdef DEBUG
2324      -        if (rfs3_do_post_op_attr) {
2325      -                va.va_mask = AT_ALL;
2326      -                vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
2327      -        } else
2328      -                vap = NULL;
2329      -#else
2330 2156          va.va_mask = AT_ALL;
2331 2157          vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
2332      -#endif
2333 2158  
2334 2159          /*
2335 2160           * Force modified data and metadata out to stable storage.
2336 2161           */
2337 2162          (void) VOP_FSYNC(vp, 0, cr, NULL);
2338 2163  
2339 2164          VN_RELE(vp);
2340 2165  
2341 2166          vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
2342 2167          vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
2343 2168          goto out;
2344 2169  
2345 2170  err:
2346 2171          if (curthread->t_flag & T_WOULDBLOCK) {
2347 2172                  curthread->t_flag &= ~T_WOULDBLOCK;
2348 2173                  resp->status = NFS3ERR_JUKEBOX;
2349 2174          } else
2350 2175                  resp->status = puterrno3(error);
2351 2176  err1:
2352 2177          vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
2353 2178  out:
2354 2179          if (name != NULL && name != args->where.name)
2355 2180                  kmem_free(name, MAXPATHLEN + 1);
2356 2181          if (symdata != NULL && symdata != args->symlink.symlink_data)
2357 2182                  kmem_free(symdata, MAXPATHLEN + 1);
2358 2183  
2359 2184          DTRACE_NFSV3_4(op__symlink__done, struct svc_req *, req,
2360 2185              cred_t *, cr, vnode_t *, dvp, SYMLINK3res *, resp);
2361 2186  
2362 2187          if (dvp != NULL)
2363 2188                  VN_RELE(dvp);
2364 2189  }
2365 2190  
2366 2191  void *
2367 2192  rfs3_symlink_getfh(SYMLINK3args *args)
2368 2193  {
2369 2194  
2370 2195          return (&args->where.dir);
2371 2196  }
2372 2197  
2373 2198  void
2374 2199  rfs3_mknod(MKNOD3args *args, MKNOD3res *resp, struct exportinfo *exi,
2375 2200          struct svc_req *req, cred_t *cr)
2376 2201  {
2377 2202          int error;
2378 2203          vnode_t *vp;
2379 2204          vnode_t *realvp;
2380 2205          vnode_t *dvp;
2381 2206          struct vattr *vap;
2382 2207          struct vattr va;
2383 2208          struct vattr *dbvap;
2384 2209          struct vattr dbva;
2385 2210          struct vattr *davap;
2386 2211          struct vattr dava;
2387 2212          int mode;
2388 2213          enum vcexcl excl;
2389 2214          struct sockaddr *ca;
2390 2215          char *name = NULL;
2391 2216  
2392 2217          dbvap = NULL;
2393 2218          davap = NULL;
2394 2219  
  
    | ↓ open down ↓ | 52 lines elided | ↑ open up ↑ | 
2395 2220          dvp = nfs3_fhtovp(&args->where.dir, exi);
2396 2221  
2397 2222          DTRACE_NFSV3_4(op__mknod__start, struct svc_req *, req,
2398 2223              cred_t *, cr, vnode_t *, dvp, MKNOD3args *, args);
2399 2224  
2400 2225          if (dvp == NULL) {
2401 2226                  error = ESTALE;
2402 2227                  goto out;
2403 2228          }
2404 2229  
2405      -#ifdef DEBUG
2406      -        if (rfs3_do_pre_op_attr) {
2407      -                dbva.va_mask = AT_ALL;
2408      -                dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
2409      -        } else
2410      -                dbvap = NULL;
2411      -#else
2412 2230          dbva.va_mask = AT_ALL;
2413 2231          dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva;
2414      -#endif
2415 2232          davap = dbvap;
2416 2233  
2417 2234          if (args->where.name == nfs3nametoolong) {
2418 2235                  resp->status = NFS3ERR_NAMETOOLONG;
2419 2236                  goto out1;
2420 2237          }
2421 2238  
2422 2239          if (args->where.name == NULL || *(args->where.name) == '\0') {
2423 2240                  resp->status = NFS3ERR_ACCES;
2424 2241                  goto out1;
2425 2242          }
2426 2243  
2427 2244          if (rdonly(exi, req)) {
2428 2245                  resp->status = NFS3ERR_ROFS;
2429 2246                  goto out1;
2430 2247          }
2431 2248  
2432 2249          if (is_system_labeled()) {
2433 2250                  bslabel_t *clabel = req->rq_label;
2434 2251  
2435 2252                  ASSERT(clabel != NULL);
2436 2253                  DTRACE_PROBE2(tx__rfs3__log__info__opmknod__clabel, char *,
2437 2254                      "got client label from request(1)", struct svc_req *, req);
2438 2255  
2439 2256                  if (!blequal(&l_admin_low->tsl_label, clabel)) {
2440 2257                          if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK,
2441 2258                              exi)) {
2442 2259                                  resp->status = NFS3ERR_ACCES;
2443 2260                                  goto out1;
2444 2261                          }
2445 2262                  }
2446 2263          }
2447 2264  
2448 2265          switch (args->what.type) {
2449 2266          case NF3CHR:
2450 2267          case NF3BLK:
2451 2268                  error = sattr3_to_vattr(
2452 2269                      &args->what.mknoddata3_u.device.dev_attributes, &va);
2453 2270                  if (error)
2454 2271                          goto out;
2455 2272                  if (secpolicy_sys_devices(cr) != 0) {
2456 2273                          resp->status = NFS3ERR_PERM;
2457 2274                          goto out1;
2458 2275                  }
2459 2276                  if (args->what.type == NF3CHR)
2460 2277                          va.va_type = VCHR;
2461 2278                  else
2462 2279                          va.va_type = VBLK;
2463 2280                  va.va_rdev = makedevice(
2464 2281                      args->what.mknoddata3_u.device.spec.specdata1,
2465 2282                      args->what.mknoddata3_u.device.spec.specdata2);
2466 2283                  va.va_mask |= AT_TYPE | AT_RDEV;
2467 2284                  break;
2468 2285          case NF3SOCK:
2469 2286                  error = sattr3_to_vattr(
2470 2287                      &args->what.mknoddata3_u.pipe_attributes, &va);
2471 2288                  if (error)
2472 2289                          goto out;
2473 2290                  va.va_type = VSOCK;
2474 2291                  va.va_mask |= AT_TYPE;
2475 2292                  break;
2476 2293          case NF3FIFO:
2477 2294                  error = sattr3_to_vattr(
2478 2295                      &args->what.mknoddata3_u.pipe_attributes, &va);
2479 2296                  if (error)
2480 2297                          goto out;
2481 2298                  va.va_type = VFIFO;
2482 2299                  va.va_mask |= AT_TYPE;
2483 2300                  break;
2484 2301          default:
2485 2302                  resp->status = NFS3ERR_BADTYPE;
2486 2303                  goto out1;
2487 2304          }
2488 2305  
2489 2306          /*
2490 2307           * Must specify the mode.
2491 2308           */
2492 2309          if (!(va.va_mask & AT_MODE)) {
2493 2310                  resp->status = NFS3ERR_INVAL;
2494 2311                  goto out1;
2495 2312          }
2496 2313  
2497 2314          ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2498 2315          name = nfscmd_convname(ca, exi, args->where.name,
2499 2316              NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2500 2317  
2501 2318          if (name == NULL) {
2502 2319                  resp->status = NFS3ERR_INVAL;
2503 2320                  goto out1;
2504 2321          }
2505 2322  
  
    | ↓ open down ↓ | 81 lines elided | ↑ open up ↑ | 
2506 2323          excl = EXCL;
2507 2324  
2508 2325          mode = 0;
2509 2326  
2510 2327          error = VOP_CREATE(dvp, name, &va, excl, mode,
2511 2328              &vp, cr, 0, NULL, NULL);
2512 2329  
2513 2330          if (name != args->where.name)
2514 2331                  kmem_free(name, MAXPATHLEN + 1);
2515 2332  
2516      -#ifdef DEBUG
2517      -        if (rfs3_do_post_op_attr) {
2518      -                dava.va_mask = AT_ALL;
2519      -                davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
2520      -        } else
2521      -                davap = NULL;
2522      -#else
2523 2333          dava.va_mask = AT_ALL;
2524 2334          davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava;
2525      -#endif
2526 2335  
2527 2336          /*
2528 2337           * Force modified data and metadata out to stable storage.
2529 2338           */
2530 2339          (void) VOP_FSYNC(dvp, 0, cr, NULL);
2531 2340  
2532 2341          if (error)
2533 2342                  goto out;
2534 2343  
2535 2344          resp->status = NFS3_OK;
2536 2345  
2537      -#ifdef DEBUG
2538      -        if (!rfs3_do_post_op_fh3)
2539      -                resp->resok.obj.handle_follows = FALSE;
2540      -        else {
2541      -#endif
2542 2346          error = makefh3(&resp->resok.obj.handle, vp, exi);
2543 2347          if (error)
2544 2348                  resp->resok.obj.handle_follows = FALSE;
2545 2349          else
2546 2350                  resp->resok.obj.handle_follows = TRUE;
2547      -#ifdef DEBUG
2548      -        }
2549      -#endif
2550 2351  
2551      -#ifdef DEBUG
2552      -        if (rfs3_do_post_op_attr) {
2553      -                va.va_mask = AT_ALL;
2554      -                vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
2555      -        } else
2556      -                vap = NULL;
2557      -#else
2558 2352          va.va_mask = AT_ALL;
2559 2353          vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
2560      -#endif
2561 2354  
2562 2355          /*
2563 2356           * Force modified metadata out to stable storage.
2564 2357           *
2565 2358           * if a underlying vp exists, pass it to VOP_FSYNC
2566 2359           */
2567 2360          if (VOP_REALVP(vp, &realvp, NULL) == 0)
2568 2361                  (void) VOP_FSYNC(realvp, FNODSYNC, cr, NULL);
2569 2362          else
2570 2363                  (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
2571 2364  
2572 2365          VN_RELE(vp);
2573 2366  
2574 2367          vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
2575 2368          vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
2576 2369          DTRACE_NFSV3_4(op__mknod__done, struct svc_req *, req,
2577 2370              cred_t *, cr, vnode_t *, dvp, MKNOD3res *, resp);
2578 2371          VN_RELE(dvp);
2579 2372          return;
2580 2373  
2581 2374  out:
2582 2375          if (curthread->t_flag & T_WOULDBLOCK) {
2583 2376                  curthread->t_flag &= ~T_WOULDBLOCK;
2584 2377                  resp->status = NFS3ERR_JUKEBOX;
2585 2378          } else
2586 2379                  resp->status = puterrno3(error);
2587 2380  out1:
2588 2381          DTRACE_NFSV3_4(op__mknod__done, struct svc_req *, req,
2589 2382              cred_t *, cr, vnode_t *, dvp, MKNOD3res *, resp);
2590 2383          if (dvp != NULL)
2591 2384                  VN_RELE(dvp);
2592 2385          vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
2593 2386  }
2594 2387  
2595 2388  void *
2596 2389  rfs3_mknod_getfh(MKNOD3args *args)
2597 2390  {
2598 2391  
2599 2392          return (&args->where.dir);
2600 2393  }
2601 2394  
2602 2395  void
2603 2396  rfs3_remove(REMOVE3args *args, REMOVE3res *resp, struct exportinfo *exi,
2604 2397          struct svc_req *req, cred_t *cr)
2605 2398  {
2606 2399          int error = 0;
2607 2400          vnode_t *vp;
2608 2401          struct vattr *bvap;
2609 2402          struct vattr bva;
2610 2403          struct vattr *avap;
2611 2404          struct vattr ava;
2612 2405          vnode_t *targvp = NULL;
2613 2406          struct sockaddr *ca;
2614 2407          char *name = NULL;
2615 2408  
2616 2409          bvap = NULL;
2617 2410          avap = NULL;
2618 2411  
  
    | ↓ open down ↓ | 48 lines elided | ↑ open up ↑ | 
2619 2412          vp = nfs3_fhtovp(&args->object.dir, exi);
2620 2413  
2621 2414          DTRACE_NFSV3_4(op__remove__start, struct svc_req *, req,
2622 2415              cred_t *, cr, vnode_t *, vp, REMOVE3args *, args);
2623 2416  
2624 2417          if (vp == NULL) {
2625 2418                  error = ESTALE;
2626 2419                  goto err;
2627 2420          }
2628 2421  
2629      -#ifdef DEBUG
2630      -        if (rfs3_do_pre_op_attr) {
2631      -                bva.va_mask = AT_ALL;
2632      -                bvap = VOP_GETATTR(vp, &bva, 0, cr, NULL) ? NULL : &bva;
2633      -        } else
2634      -                bvap = NULL;
2635      -#else
2636 2422          bva.va_mask = AT_ALL;
2637 2423          bvap = VOP_GETATTR(vp, &bva, 0, cr, NULL) ? NULL : &bva;
2638      -#endif
2639 2424          avap = bvap;
2640 2425  
2641 2426          if (vp->v_type != VDIR) {
2642 2427                  resp->status = NFS3ERR_NOTDIR;
2643 2428                  goto err1;
2644 2429          }
2645 2430  
2646 2431          if (args->object.name == nfs3nametoolong) {
2647 2432                  resp->status = NFS3ERR_NAMETOOLONG;
2648 2433                  goto err1;
2649 2434          }
2650 2435  
2651 2436          if (args->object.name == NULL || *(args->object.name) == '\0') {
2652 2437                  resp->status = NFS3ERR_ACCES;
2653 2438                  goto err1;
2654 2439          }
2655 2440  
2656 2441          if (rdonly(exi, req)) {
2657 2442                  resp->status = NFS3ERR_ROFS;
2658 2443                  goto err1;
2659 2444          }
2660 2445  
2661 2446          if (is_system_labeled()) {
2662 2447                  bslabel_t *clabel = req->rq_label;
2663 2448  
2664 2449                  ASSERT(clabel != NULL);
2665 2450                  DTRACE_PROBE2(tx__rfs3__log__info__opremove__clabel, char *,
2666 2451                      "got client label from request(1)", struct svc_req *, req);
2667 2452  
2668 2453                  if (!blequal(&l_admin_low->tsl_label, clabel)) {
2669 2454                          if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
2670 2455                              exi)) {
2671 2456                                  resp->status = NFS3ERR_ACCES;
2672 2457                                  goto err1;
2673 2458                          }
2674 2459                  }
2675 2460          }
2676 2461  
2677 2462          ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2678 2463          name = nfscmd_convname(ca, exi, args->object.name,
2679 2464              NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2680 2465  
2681 2466          if (name == NULL) {
2682 2467                  resp->status = NFS3ERR_INVAL;
2683 2468                  goto err1;
2684 2469          }
2685 2470  
2686 2471          /*
2687 2472           * Check for a conflict with a non-blocking mandatory share
2688 2473           * reservation and V4 delegations
2689 2474           */
2690 2475          error = VOP_LOOKUP(vp, name, &targvp, NULL, 0,
2691 2476              NULL, cr, NULL, NULL, NULL);
2692 2477          if (error != 0)
2693 2478                  goto err;
2694 2479  
2695 2480          if (rfs4_check_delegated(FWRITE, targvp, TRUE)) {
2696 2481                  resp->status = NFS3ERR_JUKEBOX;
2697 2482                  goto err1;
2698 2483          }
2699 2484  
2700 2485          if (!nbl_need_check(targvp)) {
2701 2486                  error = VOP_REMOVE(vp, name, cr, NULL, 0);
2702 2487          } else {
2703 2488                  nbl_start_crit(targvp, RW_READER);
  
    | ↓ open down ↓ | 55 lines elided | ↑ open up ↑ | 
2704 2489                  if (nbl_conflict(targvp, NBL_REMOVE, 0, 0, 0, NULL)) {
2705 2490                          error = EACCES;
2706 2491                  } else {
2707 2492                          error = VOP_REMOVE(vp, name, cr, NULL, 0);
2708 2493                  }
2709 2494                  nbl_end_crit(targvp);
2710 2495          }
2711 2496          VN_RELE(targvp);
2712 2497          targvp = NULL;
2713 2498  
2714      -#ifdef DEBUG
2715      -        if (rfs3_do_post_op_attr) {
2716      -                ava.va_mask = AT_ALL;
2717      -                avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
2718      -        } else
2719      -                avap = NULL;
2720      -#else
2721 2499          ava.va_mask = AT_ALL;
2722 2500          avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
2723      -#endif
2724 2501  
2725 2502          /*
2726 2503           * Force modified data and metadata out to stable storage.
2727 2504           */
2728 2505          (void) VOP_FSYNC(vp, 0, cr, NULL);
2729 2506  
2730 2507          if (error)
2731 2508                  goto err;
2732 2509  
2733 2510          resp->status = NFS3_OK;
2734 2511          vattr_to_wcc_data(bvap, avap, &resp->resok.dir_wcc);
2735 2512          goto out;
2736 2513  
2737 2514  err:
2738 2515          if (curthread->t_flag & T_WOULDBLOCK) {
2739 2516                  curthread->t_flag &= ~T_WOULDBLOCK;
2740 2517                  resp->status = NFS3ERR_JUKEBOX;
2741 2518          } else
2742 2519                  resp->status = puterrno3(error);
2743 2520  err1:
2744 2521          vattr_to_wcc_data(bvap, avap, &resp->resfail.dir_wcc);
2745 2522  out:
2746 2523          DTRACE_NFSV3_4(op__remove__done, struct svc_req *, req,
2747 2524              cred_t *, cr, vnode_t *, vp, REMOVE3res *, resp);
2748 2525  
2749 2526          if (name != NULL && name != args->object.name)
2750 2527                  kmem_free(name, MAXPATHLEN + 1);
2751 2528  
2752 2529          if (vp != NULL)
2753 2530                  VN_RELE(vp);
2754 2531  }
2755 2532  
2756 2533  void *
2757 2534  rfs3_remove_getfh(REMOVE3args *args)
2758 2535  {
2759 2536  
2760 2537          return (&args->object.dir);
2761 2538  }
2762 2539  
2763 2540  void
2764 2541  rfs3_rmdir(RMDIR3args *args, RMDIR3res *resp, struct exportinfo *exi,
2765 2542          struct svc_req *req, cred_t *cr)
2766 2543  {
2767 2544          int error;
2768 2545          vnode_t *vp;
2769 2546          struct vattr *bvap;
2770 2547          struct vattr bva;
2771 2548          struct vattr *avap;
2772 2549          struct vattr ava;
2773 2550          struct sockaddr *ca;
2774 2551          char *name = NULL;
2775 2552  
2776 2553          bvap = NULL;
2777 2554          avap = NULL;
2778 2555  
  
    | ↓ open down ↓ | 45 lines elided | ↑ open up ↑ | 
2779 2556          vp = nfs3_fhtovp(&args->object.dir, exi);
2780 2557  
2781 2558          DTRACE_NFSV3_4(op__rmdir__start, struct svc_req *, req,
2782 2559              cred_t *, cr, vnode_t *, vp, RMDIR3args *, args);
2783 2560  
2784 2561          if (vp == NULL) {
2785 2562                  error = ESTALE;
2786 2563                  goto err;
2787 2564          }
2788 2565  
2789      -#ifdef DEBUG
2790      -        if (rfs3_do_pre_op_attr) {
2791      -                bva.va_mask = AT_ALL;
2792      -                bvap = VOP_GETATTR(vp, &bva, 0, cr, NULL) ? NULL : &bva;
2793      -        } else
2794      -                bvap = NULL;
2795      -#else
2796 2566          bva.va_mask = AT_ALL;
2797 2567          bvap = VOP_GETATTR(vp, &bva, 0, cr, NULL) ? NULL : &bva;
2798      -#endif
2799 2568          avap = bvap;
2800 2569  
2801 2570          if (vp->v_type != VDIR) {
2802 2571                  resp->status = NFS3ERR_NOTDIR;
2803 2572                  goto err1;
2804 2573          }
2805 2574  
2806 2575          if (args->object.name == nfs3nametoolong) {
2807 2576                  resp->status = NFS3ERR_NAMETOOLONG;
2808 2577                  goto err1;
2809 2578          }
2810 2579  
2811 2580          if (args->object.name == NULL || *(args->object.name) == '\0') {
2812 2581                  resp->status = NFS3ERR_ACCES;
2813 2582                  goto err1;
2814 2583          }
2815 2584  
2816 2585          if (rdonly(exi, req)) {
2817 2586                  resp->status = NFS3ERR_ROFS;
2818 2587                  goto err1;
2819 2588          }
2820 2589  
2821 2590          if (is_system_labeled()) {
2822 2591                  bslabel_t *clabel = req->rq_label;
2823 2592  
2824 2593                  ASSERT(clabel != NULL);
2825 2594                  DTRACE_PROBE2(tx__rfs3__log__info__opremovedir__clabel, char *,
2826 2595                      "got client label from request(1)", struct svc_req *, req);
2827 2596  
2828 2597                  if (!blequal(&l_admin_low->tsl_label, clabel)) {
2829 2598                          if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
2830 2599                              exi)) {
2831 2600                                  resp->status = NFS3ERR_ACCES;
2832 2601                                  goto err1;
2833 2602                          }
2834 2603                  }
2835 2604          }
2836 2605  
2837 2606          ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
2838 2607          name = nfscmd_convname(ca, exi, args->object.name,
2839 2608              NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
2840 2609  
  
    | ↓ open down ↓ | 32 lines elided | ↑ open up ↑ | 
2841 2610          if (name == NULL) {
2842 2611                  resp->status = NFS3ERR_INVAL;
2843 2612                  goto err1;
2844 2613          }
2845 2614  
2846 2615          error = VOP_RMDIR(vp, name, rootdir, cr, NULL, 0);
2847 2616  
2848 2617          if (name != args->object.name)
2849 2618                  kmem_free(name, MAXPATHLEN + 1);
2850 2619  
2851      -#ifdef DEBUG
2852      -        if (rfs3_do_post_op_attr) {
2853      -                ava.va_mask = AT_ALL;
2854      -                avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
2855      -        } else
2856      -                avap = NULL;
2857      -#else
2858 2620          ava.va_mask = AT_ALL;
2859 2621          avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
2860      -#endif
2861 2622  
2862 2623          /*
2863 2624           * Force modified data and metadata out to stable storage.
2864 2625           */
2865 2626          (void) VOP_FSYNC(vp, 0, cr, NULL);
2866 2627  
2867 2628          if (error) {
2868 2629                  /*
2869 2630                   * System V defines rmdir to return EEXIST, not ENOTEMPTY,
2870 2631                   * if the directory is not empty.  A System V NFS server
2871 2632                   * needs to map NFS3ERR_EXIST to NFS3ERR_NOTEMPTY to transmit
2872 2633                   * over the wire.
2873 2634                   */
2874 2635                  if (error == EEXIST)
2875 2636                          error = ENOTEMPTY;
2876 2637                  goto err;
2877 2638          }
2878 2639  
2879 2640          resp->status = NFS3_OK;
2880 2641          vattr_to_wcc_data(bvap, avap, &resp->resok.dir_wcc);
2881 2642          goto out;
2882 2643  
2883 2644  err:
2884 2645          if (curthread->t_flag & T_WOULDBLOCK) {
2885 2646                  curthread->t_flag &= ~T_WOULDBLOCK;
2886 2647                  resp->status = NFS3ERR_JUKEBOX;
2887 2648          } else
2888 2649                  resp->status = puterrno3(error);
2889 2650  err1:
2890 2651          vattr_to_wcc_data(bvap, avap, &resp->resfail.dir_wcc);
2891 2652  out:
2892 2653          DTRACE_NFSV3_4(op__rmdir__done, struct svc_req *, req,
2893 2654              cred_t *, cr, vnode_t *, vp, RMDIR3res *, resp);
2894 2655          if (vp != NULL)
2895 2656                  VN_RELE(vp);
2896 2657  
2897 2658  }
2898 2659  
2899 2660  void *
2900 2661  rfs3_rmdir_getfh(RMDIR3args *args)
2901 2662  {
2902 2663  
2903 2664          return (&args->object.dir);
2904 2665  }
2905 2666  
2906 2667  void
2907 2668  rfs3_rename(RENAME3args *args, RENAME3res *resp, struct exportinfo *exi,
2908 2669          struct svc_req *req, cred_t *cr)
2909 2670  {
2910 2671          int error = 0;
2911 2672          vnode_t *fvp;
2912 2673          vnode_t *tvp;
2913 2674          vnode_t *targvp;
2914 2675          struct vattr *fbvap;
2915 2676          struct vattr fbva;
2916 2677          struct vattr *favap;
2917 2678          struct vattr fava;
2918 2679          struct vattr *tbvap;
2919 2680          struct vattr tbva;
2920 2681          struct vattr *tavap;
2921 2682          struct vattr tava;
2922 2683          nfs_fh3 *fh3;
2923 2684          struct exportinfo *to_exi;
2924 2685          vnode_t *srcvp = NULL;
2925 2686          bslabel_t *clabel;
2926 2687          struct sockaddr *ca;
2927 2688          char *name = NULL;
2928 2689          char *toname = NULL;
2929 2690  
2930 2691          fbvap = NULL;
2931 2692          favap = NULL;
2932 2693          tbvap = NULL;
2933 2694          tavap = NULL;
2934 2695          tvp = NULL;
2935 2696  
2936 2697          fvp = nfs3_fhtovp(&args->from.dir, exi);
2937 2698  
2938 2699          DTRACE_NFSV3_4(op__rename__start, struct svc_req *, req,
2939 2700              cred_t *, cr, vnode_t *, fvp, RENAME3args *, args);
2940 2701  
2941 2702          if (fvp == NULL) {
2942 2703                  error = ESTALE;
2943 2704                  goto err;
2944 2705          }
2945 2706  
2946 2707          if (is_system_labeled()) {
2947 2708                  clabel = req->rq_label;
2948 2709                  ASSERT(clabel != NULL);
2949 2710                  DTRACE_PROBE2(tx__rfs3__log__info__oprename__clabel, char *,
2950 2711                      "got client label from request(1)", struct svc_req *, req);
  
    | ↓ open down ↓ | 80 lines elided | ↑ open up ↑ | 
2951 2712  
2952 2713                  if (!blequal(&l_admin_low->tsl_label, clabel)) {
2953 2714                          if (!do_rfs_label_check(clabel, fvp, EQUALITY_CHECK,
2954 2715                              exi)) {
2955 2716                                  resp->status = NFS3ERR_ACCES;
2956 2717                                  goto err1;
2957 2718                          }
2958 2719                  }
2959 2720          }
2960 2721  
2961      -#ifdef DEBUG
2962      -        if (rfs3_do_pre_op_attr) {
2963      -                fbva.va_mask = AT_ALL;
2964      -                fbvap = VOP_GETATTR(fvp, &fbva, 0, cr, NULL) ? NULL : &fbva;
2965      -        } else
2966      -                fbvap = NULL;
2967      -#else
2968 2722          fbva.va_mask = AT_ALL;
2969 2723          fbvap = VOP_GETATTR(fvp, &fbva, 0, cr, NULL) ? NULL : &fbva;
2970      -#endif
2971 2724          favap = fbvap;
2972 2725  
2973 2726          fh3 = &args->to.dir;
2974 2727          to_exi = checkexport(&fh3->fh3_fsid, FH3TOXFIDP(fh3));
2975 2728          if (to_exi == NULL) {
2976 2729                  resp->status = NFS3ERR_ACCES;
2977 2730                  goto err1;
2978 2731          }
2979 2732          exi_rele(to_exi);
2980 2733  
2981 2734          if (to_exi != exi) {
  
    | ↓ open down ↓ | 1 lines elided | ↑ open up ↑ | 
2982 2735                  resp->status = NFS3ERR_XDEV;
2983 2736                  goto err1;
2984 2737          }
2985 2738  
2986 2739          tvp = nfs3_fhtovp(&args->to.dir, exi);
2987 2740          if (tvp == NULL) {
2988 2741                  error = ESTALE;
2989 2742                  goto err;
2990 2743          }
2991 2744  
2992      -#ifdef DEBUG
2993      -        if (rfs3_do_pre_op_attr) {
2994      -                tbva.va_mask = AT_ALL;
2995      -                tbvap = VOP_GETATTR(tvp, &tbva, 0, cr, NULL) ? NULL : &tbva;
2996      -        } else
2997      -                tbvap = NULL;
2998      -#else
2999 2745          tbva.va_mask = AT_ALL;
3000 2746          tbvap = VOP_GETATTR(tvp, &tbva, 0, cr, NULL) ? NULL : &tbva;
3001      -#endif
3002 2747          tavap = tbvap;
3003 2748  
3004 2749          if (fvp->v_type != VDIR || tvp->v_type != VDIR) {
3005 2750                  resp->status = NFS3ERR_NOTDIR;
3006 2751                  goto err1;
3007 2752          }
3008 2753  
3009 2754          if (args->from.name == nfs3nametoolong ||
3010 2755              args->to.name == nfs3nametoolong) {
3011 2756                  resp->status = NFS3ERR_NAMETOOLONG;
3012 2757                  goto err1;
3013 2758          }
3014 2759          if (args->from.name == NULL || *(args->from.name) == '\0' ||
3015 2760              args->to.name == NULL || *(args->to.name) == '\0') {
3016 2761                  resp->status = NFS3ERR_ACCES;
3017 2762                  goto err1;
3018 2763          }
3019 2764  
3020 2765          if (rdonly(exi, req)) {
3021 2766                  resp->status = NFS3ERR_ROFS;
3022 2767                  goto err1;
3023 2768          }
3024 2769  
3025 2770          if (is_system_labeled()) {
3026 2771                  if (!blequal(&l_admin_low->tsl_label, clabel)) {
3027 2772                          if (!do_rfs_label_check(clabel, tvp, EQUALITY_CHECK,
3028 2773                              exi)) {
3029 2774                                  resp->status = NFS3ERR_ACCES;
3030 2775                                  goto err1;
3031 2776                          }
3032 2777                  }
3033 2778          }
3034 2779  
3035 2780          ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
3036 2781          name = nfscmd_convname(ca, exi, args->from.name,
3037 2782              NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
3038 2783  
3039 2784          if (name == NULL) {
3040 2785                  resp->status = NFS3ERR_INVAL;
3041 2786                  goto err1;
3042 2787          }
3043 2788  
3044 2789          toname = nfscmd_convname(ca, exi, args->to.name,
3045 2790              NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
3046 2791  
3047 2792          if (toname == NULL) {
3048 2793                  resp->status = NFS3ERR_INVAL;
3049 2794                  goto err1;
3050 2795          }
3051 2796  
3052 2797          /*
3053 2798           * Check for a conflict with a non-blocking mandatory share
3054 2799           * reservation or V4 delegations.
3055 2800           */
3056 2801          error = VOP_LOOKUP(fvp, name, &srcvp, NULL, 0,
3057 2802              NULL, cr, NULL, NULL, NULL);
3058 2803          if (error != 0)
3059 2804                  goto err;
3060 2805  
3061 2806          /*
3062 2807           * If we rename a delegated file we should recall the
3063 2808           * delegation, since future opens should fail or would
3064 2809           * refer to a new file.
3065 2810           */
3066 2811          if (rfs4_check_delegated(FWRITE, srcvp, FALSE)) {
3067 2812                  resp->status = NFS3ERR_JUKEBOX;
3068 2813                  goto err1;
3069 2814          }
3070 2815  
3071 2816          /*
3072 2817           * Check for renaming over a delegated file.  Check rfs4_deleg_policy
3073 2818           * first to avoid VOP_LOOKUP if possible.
3074 2819           */
3075 2820          if (rfs4_deleg_policy != SRV_NEVER_DELEGATE &&
3076 2821              VOP_LOOKUP(tvp, toname, &targvp, NULL, 0, NULL, cr,
3077 2822              NULL, NULL, NULL) == 0) {
3078 2823  
3079 2824                  if (rfs4_check_delegated(FWRITE, targvp, TRUE)) {
3080 2825                          VN_RELE(targvp);
3081 2826                          resp->status = NFS3ERR_JUKEBOX;
3082 2827                          goto err1;
3083 2828                  }
3084 2829                  VN_RELE(targvp);
3085 2830          }
3086 2831  
3087 2832          if (!nbl_need_check(srcvp)) {
3088 2833                  error = VOP_RENAME(fvp, name, tvp, toname, cr, NULL, 0);
3089 2834          } else {
3090 2835                  nbl_start_crit(srcvp, RW_READER);
3091 2836                  if (nbl_conflict(srcvp, NBL_RENAME, 0, 0, 0, NULL))
3092 2837                          error = EACCES;
  
    | ↓ open down ↓ | 81 lines elided | ↑ open up ↑ | 
3093 2838                  else
3094 2839                          error = VOP_RENAME(fvp, name, tvp, toname, cr, NULL, 0);
3095 2840                  nbl_end_crit(srcvp);
3096 2841          }
3097 2842          if (error == 0)
3098 2843                  vn_renamepath(tvp, srcvp, args->to.name,
3099 2844                      strlen(args->to.name));
3100 2845          VN_RELE(srcvp);
3101 2846          srcvp = NULL;
3102 2847  
3103      -#ifdef DEBUG
3104      -        if (rfs3_do_post_op_attr) {
3105      -                fava.va_mask = AT_ALL;
3106      -                favap = VOP_GETATTR(fvp, &fava, 0, cr, NULL) ? NULL : &fava;
3107      -                tava.va_mask = AT_ALL;
3108      -                tavap = VOP_GETATTR(tvp, &tava, 0, cr, NULL) ? NULL : &tava;
3109      -        } else {
3110      -                favap = NULL;
3111      -                tavap = NULL;
3112      -        }
3113      -#else
3114 2848          fava.va_mask = AT_ALL;
3115 2849          favap = VOP_GETATTR(fvp, &fava, 0, cr, NULL) ? NULL : &fava;
3116 2850          tava.va_mask = AT_ALL;
3117 2851          tavap = VOP_GETATTR(tvp, &tava, 0, cr, NULL) ? NULL : &tava;
3118      -#endif
3119 2852  
3120 2853          /*
3121 2854           * Force modified data and metadata out to stable storage.
3122 2855           */
3123 2856          (void) VOP_FSYNC(fvp, 0, cr, NULL);
3124 2857          (void) VOP_FSYNC(tvp, 0, cr, NULL);
3125 2858  
3126 2859          if (error)
3127 2860                  goto err;
3128 2861  
3129 2862          resp->status = NFS3_OK;
3130 2863          vattr_to_wcc_data(fbvap, favap, &resp->resok.fromdir_wcc);
3131 2864          vattr_to_wcc_data(tbvap, tavap, &resp->resok.todir_wcc);
3132 2865          goto out;
3133 2866  
3134 2867  err:
3135 2868          if (curthread->t_flag & T_WOULDBLOCK) {
3136 2869                  curthread->t_flag &= ~T_WOULDBLOCK;
3137 2870                  resp->status = NFS3ERR_JUKEBOX;
3138 2871          } else {
3139 2872                  resp->status = puterrno3(error);
3140 2873          }
3141 2874  err1:
3142 2875          vattr_to_wcc_data(fbvap, favap, &resp->resfail.fromdir_wcc);
3143 2876          vattr_to_wcc_data(tbvap, tavap, &resp->resfail.todir_wcc);
3144 2877  
3145 2878  out:
3146 2879          if (name != NULL && name != args->from.name)
3147 2880                  kmem_free(name, MAXPATHLEN + 1);
3148 2881          if (toname != NULL && toname != args->to.name)
3149 2882                  kmem_free(toname, MAXPATHLEN + 1);
3150 2883  
3151 2884          DTRACE_NFSV3_4(op__rename__done, struct svc_req *, req,
3152 2885              cred_t *, cr, vnode_t *, fvp, RENAME3res *, resp);
3153 2886          if (fvp != NULL)
3154 2887                  VN_RELE(fvp);
3155 2888          if (tvp != NULL)
3156 2889                  VN_RELE(tvp);
3157 2890  }
3158 2891  
3159 2892  void *
3160 2893  rfs3_rename_getfh(RENAME3args *args)
3161 2894  {
3162 2895  
3163 2896          return (&args->from.dir);
3164 2897  }
3165 2898  
3166 2899  void
3167 2900  rfs3_link(LINK3args *args, LINK3res *resp, struct exportinfo *exi,
3168 2901          struct svc_req *req, cred_t *cr)
3169 2902  {
3170 2903          int error;
3171 2904          vnode_t *vp;
3172 2905          vnode_t *dvp;
3173 2906          struct vattr *vap;
3174 2907          struct vattr va;
3175 2908          struct vattr *bvap;
3176 2909          struct vattr bva;
3177 2910          struct vattr *avap;
3178 2911          struct vattr ava;
3179 2912          nfs_fh3 *fh3;
3180 2913          struct exportinfo *to_exi;
3181 2914          bslabel_t *clabel;
3182 2915          struct sockaddr *ca;
3183 2916          char *name = NULL;
3184 2917  
3185 2918          vap = NULL;
3186 2919          bvap = NULL;
3187 2920          avap = NULL;
3188 2921          dvp = NULL;
3189 2922  
  
    | ↓ open down ↓ | 61 lines elided | ↑ open up ↑ | 
3190 2923          vp = nfs3_fhtovp(&args->file, exi);
3191 2924  
3192 2925          DTRACE_NFSV3_4(op__link__start, struct svc_req *, req,
3193 2926              cred_t *, cr, vnode_t *, vp, LINK3args *, args);
3194 2927  
3195 2928          if (vp == NULL) {
3196 2929                  error = ESTALE;
3197 2930                  goto out;
3198 2931          }
3199 2932  
3200      -#ifdef DEBUG
3201      -        if (rfs3_do_pre_op_attr) {
3202      -                va.va_mask = AT_ALL;
3203      -                vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3204      -        } else
3205      -                vap = NULL;
3206      -#else
3207 2933          va.va_mask = AT_ALL;
3208 2934          vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3209      -#endif
3210 2935  
3211 2936          fh3 = &args->link.dir;
3212 2937          to_exi = checkexport(&fh3->fh3_fsid, FH3TOXFIDP(fh3));
3213 2938          if (to_exi == NULL) {
3214 2939                  resp->status = NFS3ERR_ACCES;
3215 2940                  goto out1;
3216 2941          }
3217 2942          exi_rele(to_exi);
3218 2943  
3219 2944          if (to_exi != exi) {
3220 2945                  resp->status = NFS3ERR_XDEV;
3221 2946                  goto out1;
3222 2947          }
3223 2948  
3224 2949          if (is_system_labeled()) {
3225 2950                  clabel = req->rq_label;
3226 2951  
3227 2952                  ASSERT(clabel != NULL);
3228 2953                  DTRACE_PROBE2(tx__rfs3__log__info__oplink__clabel, char *,
3229 2954                      "got client label from request(1)", struct svc_req *, req);
3230 2955  
3231 2956                  if (!blequal(&l_admin_low->tsl_label, clabel)) {
3232 2957                          if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
3233 2958                              exi)) {
3234 2959                                  resp->status = NFS3ERR_ACCES;
3235 2960                                  goto out1;
  
    | ↓ open down ↓ | 16 lines elided | ↑ open up ↑ | 
3236 2961                          }
3237 2962                  }
3238 2963          }
3239 2964  
3240 2965          dvp = nfs3_fhtovp(&args->link.dir, exi);
3241 2966          if (dvp == NULL) {
3242 2967                  error = ESTALE;
3243 2968                  goto out;
3244 2969          }
3245 2970  
3246      -#ifdef DEBUG
3247      -        if (rfs3_do_pre_op_attr) {
3248      -                bva.va_mask = AT_ALL;
3249      -                bvap = VOP_GETATTR(dvp, &bva, 0, cr, NULL) ? NULL : &bva;
3250      -        } else
3251      -                bvap = NULL;
3252      -#else
3253 2971          bva.va_mask = AT_ALL;
3254 2972          bvap = VOP_GETATTR(dvp, &bva, 0, cr, NULL) ? NULL : &bva;
3255      -#endif
3256 2973  
3257 2974          if (dvp->v_type != VDIR) {
3258 2975                  resp->status = NFS3ERR_NOTDIR;
3259 2976                  goto out1;
3260 2977          }
3261 2978  
3262 2979          if (args->link.name == nfs3nametoolong) {
3263 2980                  resp->status = NFS3ERR_NAMETOOLONG;
3264 2981                  goto out1;
3265 2982          }
3266 2983  
3267 2984          if (args->link.name == NULL || *(args->link.name) == '\0') {
3268 2985                  resp->status = NFS3ERR_ACCES;
3269 2986                  goto out1;
3270 2987          }
3271 2988  
3272 2989          if (rdonly(exi, req)) {
3273 2990                  resp->status = NFS3ERR_ROFS;
3274 2991                  goto out1;
3275 2992          }
3276 2993  
3277 2994          if (is_system_labeled()) {
3278 2995                  DTRACE_PROBE2(tx__rfs3__log__info__oplinkdir__clabel, char *,
3279 2996                      "got client label from request(1)", struct svc_req *, req);
3280 2997  
3281 2998                  if (!blequal(&l_admin_low->tsl_label, clabel)) {
3282 2999                          if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK,
3283 3000                              exi)) {
3284 3001                                  resp->status = NFS3ERR_ACCES;
3285 3002                                  goto out1;
3286 3003                          }
3287 3004                  }
3288 3005          }
3289 3006  
3290 3007          ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
  
    | ↓ open down ↓ | 25 lines elided | ↑ open up ↑ | 
3291 3008          name = nfscmd_convname(ca, exi, args->link.name,
3292 3009              NFSCMD_CONV_INBOUND, MAXPATHLEN + 1);
3293 3010  
3294 3011          if (name == NULL) {
3295 3012                  resp->status = NFS3ERR_SERVERFAULT;
3296 3013                  goto out1;
3297 3014          }
3298 3015  
3299 3016          error = VOP_LINK(dvp, vp, name, cr, NULL, 0);
3300 3017  
3301      -#ifdef DEBUG
3302      -        if (rfs3_do_post_op_attr) {
3303      -                va.va_mask = AT_ALL;
3304      -                vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3305      -                ava.va_mask = AT_ALL;
3306      -                avap = VOP_GETATTR(dvp, &ava, 0, cr, NULL) ? NULL : &ava;
3307      -        } else {
3308      -                vap = NULL;
3309      -                avap = NULL;
3310      -        }
3311      -#else
3312 3018          va.va_mask = AT_ALL;
3313 3019          vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3314 3020          ava.va_mask = AT_ALL;
3315 3021          avap = VOP_GETATTR(dvp, &ava, 0, cr, NULL) ? NULL : &ava;
3316      -#endif
3317 3022  
3318 3023          /*
3319 3024           * Force modified data and metadata out to stable storage.
3320 3025           */
3321 3026          (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
3322 3027          (void) VOP_FSYNC(dvp, 0, cr, NULL);
3323 3028  
3324 3029          if (error)
3325 3030                  goto out;
3326 3031  
3327 3032          VN_RELE(dvp);
3328 3033  
3329 3034          resp->status = NFS3_OK;
3330 3035          vattr_to_post_op_attr(vap, &resp->resok.file_attributes);
3331 3036          vattr_to_wcc_data(bvap, avap, &resp->resok.linkdir_wcc);
3332 3037  
3333 3038          DTRACE_NFSV3_4(op__link__done, struct svc_req *, req,
3334 3039              cred_t *, cr, vnode_t *, vp, LINK3res *, resp);
3335 3040  
3336 3041          VN_RELE(vp);
3337 3042  
3338 3043          return;
3339 3044  
3340 3045  out:
3341 3046          if (curthread->t_flag & T_WOULDBLOCK) {
3342 3047                  curthread->t_flag &= ~T_WOULDBLOCK;
3343 3048                  resp->status = NFS3ERR_JUKEBOX;
3344 3049          } else
3345 3050                  resp->status = puterrno3(error);
3346 3051  out1:
3347 3052          if (name != NULL && name != args->link.name)
3348 3053                  kmem_free(name, MAXPATHLEN + 1);
3349 3054  
3350 3055          DTRACE_NFSV3_4(op__link__done, struct svc_req *, req,
3351 3056              cred_t *, cr, vnode_t *, vp, LINK3res *, resp);
3352 3057  
3353 3058          if (vp != NULL)
3354 3059                  VN_RELE(vp);
3355 3060          if (dvp != NULL)
3356 3061                  VN_RELE(dvp);
3357 3062          vattr_to_post_op_attr(vap, &resp->resfail.file_attributes);
3358 3063          vattr_to_wcc_data(bvap, avap, &resp->resfail.linkdir_wcc);
3359 3064  }
3360 3065  
3361 3066  void *
3362 3067  rfs3_link_getfh(LINK3args *args)
3363 3068  {
3364 3069  
3365 3070          return (&args->file);
3366 3071  }
3367 3072  
3368 3073  /*
3369 3074   * This macro defines the size of a response which contains attribute
3370 3075   * information and one directory entry (whose length is specified by
3371 3076   * the macro parameter).  If the incoming request is larger than this,
3372 3077   * then we are guaranteed to be able to return at one directory entry
3373 3078   * if one exists.  Therefore, we do not need to check for
3374 3079   * NFS3ERR_TOOSMALL if the requested size is larger then this.  If it
3375 3080   * is not, then we need to check to make sure that this error does not
3376 3081   * need to be returned.
3377 3082   *
3378 3083   * NFS3_READDIR_MIN_COUNT is comprised of following :
3379 3084   *
3380 3085   * status - 1 * BYTES_PER_XDR_UNIT
3381 3086   * attr. flag - 1 * BYTES_PER_XDR_UNIT
3382 3087   * cookie verifier - 2 * BYTES_PER_XDR_UNIT
3383 3088   * attributes  - NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT
3384 3089   * boolean - 1 * BYTES_PER_XDR_UNIT
3385 3090   * file id - 2 * BYTES_PER_XDR_UNIT
3386 3091   * directory name length - 1 * BYTES_PER_XDR_UNIT
3387 3092   * cookie - 2 * BYTES_PER_XDR_UNIT
3388 3093   * end of list - 1 * BYTES_PER_XDR_UNIT
3389 3094   * end of file - 1 * BYTES_PER_XDR_UNIT
3390 3095   * Name length of directory to the nearest byte
3391 3096   */
3392 3097  
3393 3098  #define NFS3_READDIR_MIN_COUNT(length)  \
3394 3099          ((1 + 1 + 2 + NFS3_SIZEOF_FATTR3 + 1 + 2 + 1 + 2 + 1 + 1) * \
3395 3100                  BYTES_PER_XDR_UNIT + roundup((length), BYTES_PER_XDR_UNIT))
3396 3101  
3397 3102  /* ARGSUSED */
3398 3103  void
3399 3104  rfs3_readdir(READDIR3args *args, READDIR3res *resp, struct exportinfo *exi,
3400 3105          struct svc_req *req, cred_t *cr)
3401 3106  {
3402 3107          int error;
3403 3108          vnode_t *vp;
3404 3109          struct vattr *vap;
3405 3110          struct vattr va;
3406 3111          struct iovec iov;
3407 3112          struct uio uio;
3408 3113          char *data;
3409 3114          int iseof;
3410 3115          int bufsize;
3411 3116          int namlen;
3412 3117          uint_t count;
3413 3118          struct sockaddr *ca;
3414 3119  
3415 3120          vap = NULL;
3416 3121  
3417 3122          vp = nfs3_fhtovp(&args->dir, exi);
3418 3123  
3419 3124          DTRACE_NFSV3_4(op__readdir__start, struct svc_req *, req,
3420 3125              cred_t *, cr, vnode_t *, vp, READDIR3args *, args);
3421 3126  
3422 3127          if (vp == NULL) {
3423 3128                  error = ESTALE;
3424 3129                  goto out;
3425 3130          }
3426 3131  
3427 3132          if (is_system_labeled()) {
3428 3133                  bslabel_t *clabel = req->rq_label;
3429 3134  
3430 3135                  ASSERT(clabel != NULL);
3431 3136                  DTRACE_PROBE2(tx__rfs3__log__info__opreaddir__clabel, char *,
3432 3137                      "got client label from request(1)", struct svc_req *, req);
3433 3138  
3434 3139                  if (!blequal(&l_admin_low->tsl_label, clabel)) {
  
    | ↓ open down ↓ | 108 lines elided | ↑ open up ↑ | 
3435 3140                          if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
3436 3141                              exi)) {
3437 3142                                  resp->status = NFS3ERR_ACCES;
3438 3143                                  goto out1;
3439 3144                          }
3440 3145                  }
3441 3146          }
3442 3147  
3443 3148          (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL);
3444 3149  
3445      -#ifdef DEBUG
3446      -        if (rfs3_do_pre_op_attr) {
3447      -                va.va_mask = AT_ALL;
3448      -                vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3449      -        } else
3450      -                vap = NULL;
3451      -#else
3452 3150          va.va_mask = AT_ALL;
3453 3151          vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3454      -#endif
3455 3152  
3456 3153          if (vp->v_type != VDIR) {
3457 3154                  resp->status = NFS3ERR_NOTDIR;
3458 3155                  goto out1;
3459 3156          }
3460 3157  
3461 3158          error = VOP_ACCESS(vp, VREAD, 0, cr, NULL);
3462 3159          if (error)
3463 3160                  goto out;
3464 3161  
3465 3162          /*
3466 3163           * Now don't allow arbitrary count to alloc;
3467 3164           * allow the maximum not to exceed rfs3_tsize()
3468 3165           */
3469 3166          if (args->count > rfs3_tsize(req))
3470 3167                  args->count = rfs3_tsize(req);
3471 3168  
3472 3169          /*
3473 3170           * Make sure that there is room to read at least one entry
3474 3171           * if any are available.
3475 3172           */
3476 3173          if (args->count < DIRENT64_RECLEN(MAXNAMELEN))
3477 3174                  count = DIRENT64_RECLEN(MAXNAMELEN);
3478 3175          else
3479 3176                  count = args->count;
3480 3177  
3481 3178          data = kmem_alloc(count, KM_SLEEP);
3482 3179  
3483 3180          iov.iov_base = data;
  
    | ↓ open down ↓ | 19 lines elided | ↑ open up ↑ | 
3484 3181          iov.iov_len = count;
3485 3182          uio.uio_iov = &iov;
3486 3183          uio.uio_iovcnt = 1;
3487 3184          uio.uio_segflg = UIO_SYSSPACE;
3488 3185          uio.uio_extflg = UIO_COPY_CACHED;
3489 3186          uio.uio_loffset = (offset_t)args->cookie;
3490 3187          uio.uio_resid = count;
3491 3188  
3492 3189          error = VOP_READDIR(vp, &uio, cr, &iseof, NULL, 0);
3493 3190  
3494      -#ifdef DEBUG
3495      -        if (rfs3_do_post_op_attr) {
3496      -                va.va_mask = AT_ALL;
3497      -                vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3498      -        } else
3499      -                vap = NULL;
3500      -#else
3501 3191          va.va_mask = AT_ALL;
3502 3192          vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3503      -#endif
3504 3193  
3505 3194          if (error) {
3506 3195                  kmem_free(data, count);
3507 3196                  goto out;
3508 3197          }
3509 3198  
3510 3199          /*
3511 3200           * If the count was not large enough to be able to guarantee
3512 3201           * to be able to return at least one entry, then need to
3513 3202           * check to see if NFS3ERR_TOOSMALL should be returned.
3514 3203           */
3515 3204          if (args->count < NFS3_READDIR_MIN_COUNT(MAXNAMELEN)) {
3516 3205                  /*
3517 3206                   * bufsize is used to keep track of the size of the response.
3518 3207                   * It is primed with:
3519 3208                   *      1 for the status +
3520 3209                   *      1 for the dir_attributes.attributes boolean +
3521 3210                   *      2 for the cookie verifier
3522 3211                   * all times BYTES_PER_XDR_UNIT to convert from XDR units
3523 3212                   * to bytes.  If there are directory attributes to be
3524 3213                   * returned, then:
3525 3214                   *      NFS3_SIZEOF_FATTR3 for the dir_attributes.attr fattr3
3526 3215                   * time BYTES_PER_XDR_UNIT is added to account for them.
3527 3216                   */
3528 3217                  bufsize = (1 + 1 + 2) * BYTES_PER_XDR_UNIT;
3529 3218                  if (vap != NULL)
3530 3219                          bufsize += NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT;
3531 3220                  /*
3532 3221                   * An entry is composed of:
3533 3222                   *      1 for the true/false list indicator +
3534 3223                   *      2 for the fileid +
3535 3224                   *      1 for the length of the name +
3536 3225                   *      2 for the cookie +
3537 3226                   * all times BYTES_PER_XDR_UNIT to convert from
3538 3227                   * XDR units to bytes, plus the length of the name
3539 3228                   * rounded up to the nearest BYTES_PER_XDR_UNIT.
3540 3229                   */
3541 3230                  if (count != uio.uio_resid) {
3542 3231                          namlen = strlen(((struct dirent64 *)data)->d_name);
3543 3232                          bufsize += (1 + 2 + 1 + 2) * BYTES_PER_XDR_UNIT +
3544 3233                              roundup(namlen, BYTES_PER_XDR_UNIT);
3545 3234                  }
3546 3235                  /*
3547 3236                   * We need to check to see if the number of bytes left
3548 3237                   * to go into the buffer will actually fit into the
3549 3238                   * buffer.  This is calculated as the size of this
3550 3239                   * entry plus:
3551 3240                   *      1 for the true/false list indicator +
3552 3241                   *      1 for the eof indicator
3553 3242                   * times BYTES_PER_XDR_UNIT to convert from from
3554 3243                   * XDR units to bytes.
3555 3244                   */
3556 3245                  bufsize += (1 + 1) * BYTES_PER_XDR_UNIT;
3557 3246                  if (bufsize > args->count) {
3558 3247                          kmem_free(data, count);
3559 3248                          resp->status = NFS3ERR_TOOSMALL;
3560 3249                          goto out1;
3561 3250                  }
3562 3251          }
3563 3252  
3564 3253          /*
3565 3254           * Have a valid readir buffer for the native character
3566 3255           * set. Need to check if a conversion is necessary and
3567 3256           * potentially rewrite the whole buffer. Note that if the
3568 3257           * conversion expands names enough, the structure may not
3569 3258           * fit. In this case, we need to drop entries until if fits
3570 3259           * and patch the counts in order that the next readdir will
3571 3260           * get the correct entries.
3572 3261           */
3573 3262          ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
3574 3263          data = nfscmd_convdirent(ca, exi, data, count, &resp->status);
3575 3264  
3576 3265  
3577 3266          VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
3578 3267  
3579 3268  #if 0 /* notyet */
3580 3269          /*
3581 3270           * Don't do this.  It causes local disk writes when just
3582 3271           * reading the file and the overhead is deemed larger
3583 3272           * than the benefit.
3584 3273           */
3585 3274          /*
3586 3275           * Force modified metadata out to stable storage.
3587 3276           */
3588 3277          (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
3589 3278  #endif
3590 3279  
3591 3280          resp->status = NFS3_OK;
3592 3281          vattr_to_post_op_attr(vap, &resp->resok.dir_attributes);
3593 3282          resp->resok.cookieverf = 0;
3594 3283          resp->resok.reply.entries = (entry3 *)data;
3595 3284          resp->resok.reply.eof = iseof;
3596 3285          resp->resok.size = count - uio.uio_resid;
3597 3286          resp->resok.count = args->count;
3598 3287          resp->resok.freecount = count;
3599 3288  
3600 3289          DTRACE_NFSV3_4(op__readdir__done, struct svc_req *, req,
3601 3290              cred_t *, cr, vnode_t *, vp, READDIR3res *, resp);
3602 3291  
3603 3292          VN_RELE(vp);
3604 3293  
3605 3294          return;
3606 3295  
3607 3296  out:
3608 3297          if (curthread->t_flag & T_WOULDBLOCK) {
3609 3298                  curthread->t_flag &= ~T_WOULDBLOCK;
3610 3299                  resp->status = NFS3ERR_JUKEBOX;
3611 3300          } else
3612 3301                  resp->status = puterrno3(error);
3613 3302  out1:
3614 3303          DTRACE_NFSV3_4(op__readdir__done, struct svc_req *, req,
3615 3304              cred_t *, cr, vnode_t *, vp, READDIR3res *, resp);
3616 3305  
3617 3306          if (vp != NULL) {
3618 3307                  VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
3619 3308                  VN_RELE(vp);
3620 3309          }
3621 3310          vattr_to_post_op_attr(vap, &resp->resfail.dir_attributes);
3622 3311  }
3623 3312  
3624 3313  void *
3625 3314  rfs3_readdir_getfh(READDIR3args *args)
3626 3315  {
3627 3316  
3628 3317          return (&args->dir);
3629 3318  }
3630 3319  
3631 3320  void
3632 3321  rfs3_readdir_free(READDIR3res *resp)
3633 3322  {
3634 3323  
3635 3324          if (resp->status == NFS3_OK)
3636 3325                  kmem_free(resp->resok.reply.entries, resp->resok.freecount);
3637 3326  }
3638 3327  
3639 3328  #ifdef nextdp
3640 3329  #undef nextdp
3641 3330  #endif
3642 3331  #define nextdp(dp)      ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
3643 3332  
3644 3333  /*
3645 3334   * This macro computes the size of a response which contains
3646 3335   * one directory entry including the attributes as well as file handle.
3647 3336   * If the incoming request is larger than this, then we are guaranteed to be
3648 3337   * able to return at least one more directory entry if one exists.
3649 3338   *
3650 3339   * NFS3_READDIRPLUS_ENTRY is made up of the following:
3651 3340   *
3652 3341   * boolean - 1 * BYTES_PER_XDR_UNIT
3653 3342   * file id - 2 * BYTES_PER_XDR_UNIT
3654 3343   * directory name length - 1 * BYTES_PER_XDR_UNIT
3655 3344   * cookie - 2 * BYTES_PER_XDR_UNIT
3656 3345   * attribute flag - 1 * BYTES_PER_XDR_UNIT
3657 3346   * attributes - NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT
3658 3347   * status byte for file handle - 1 *  BYTES_PER_XDR_UNIT
3659 3348   * length of a file handle - 1 * BYTES_PER_XDR_UNIT
3660 3349   * Maximum length of a file handle (NFS3_MAXFHSIZE)
3661 3350   * name length of the entry to the nearest bytes
3662 3351   */
3663 3352  #define NFS3_READDIRPLUS_ENTRY(namelen) \
3664 3353          ((1 + 2 + 1 + 2 + 1 + NFS3_SIZEOF_FATTR3 + 1 + 1) * \
3665 3354                  BYTES_PER_XDR_UNIT + \
3666 3355          NFS3_MAXFHSIZE + roundup(namelen, BYTES_PER_XDR_UNIT))
3667 3356  
3668 3357  static int rfs3_readdir_unit = MAXBSIZE;
3669 3358  
3670 3359  /* ARGSUSED */
3671 3360  void
3672 3361  rfs3_readdirplus(READDIRPLUS3args *args, READDIRPLUS3res *resp,
3673 3362          struct exportinfo *exi, struct svc_req *req, cred_t *cr)
3674 3363  {
3675 3364          int error;
3676 3365          vnode_t *vp;
3677 3366          struct vattr *vap;
3678 3367          struct vattr va;
3679 3368          struct iovec iov;
3680 3369          struct uio uio;
3681 3370          char *data;
3682 3371          int iseof;
3683 3372          struct dirent64 *dp;
3684 3373          vnode_t *nvp;
3685 3374          struct vattr *nvap;
3686 3375          struct vattr nva;
3687 3376          entryplus3_info *infop = NULL;
3688 3377          int size = 0;
3689 3378          int nents = 0;
3690 3379          int bufsize = 0;
3691 3380          int entrysize = 0;
3692 3381          int tofit = 0;
3693 3382          int rd_unit = rfs3_readdir_unit;
3694 3383          int prev_len;
3695 3384          int space_left;
3696 3385          int i;
3697 3386          uint_t *namlen = NULL;
3698 3387          char *ndata = NULL;
3699 3388          struct sockaddr *ca;
3700 3389          size_t ret;
3701 3390  
3702 3391          vap = NULL;
3703 3392  
3704 3393          vp = nfs3_fhtovp(&args->dir, exi);
3705 3394  
3706 3395          DTRACE_NFSV3_4(op__readdirplus__start, struct svc_req *, req,
3707 3396              cred_t *, cr, vnode_t *, vp, READDIRPLUS3args *, args);
3708 3397  
3709 3398          if (vp == NULL) {
3710 3399                  error = ESTALE;
3711 3400                  goto out;
3712 3401          }
3713 3402  
3714 3403          if (is_system_labeled()) {
3715 3404                  bslabel_t *clabel = req->rq_label;
3716 3405  
3717 3406                  ASSERT(clabel != NULL);
3718 3407                  DTRACE_PROBE2(tx__rfs3__log__info__opreaddirplus__clabel,
3719 3408                      char *, "got client label from request(1)",
3720 3409                      struct svc_req *, req);
3721 3410  
3722 3411                  if (!blequal(&l_admin_low->tsl_label, clabel)) {
  
    | ↓ open down ↓ | 209 lines elided | ↑ open up ↑ | 
3723 3412                          if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
3724 3413                              exi)) {
3725 3414                                  resp->status = NFS3ERR_ACCES;
3726 3415                                  goto out1;
3727 3416                          }
3728 3417                  }
3729 3418          }
3730 3419  
3731 3420          (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL);
3732 3421  
3733      -#ifdef DEBUG
3734      -        if (rfs3_do_pre_op_attr) {
3735      -                va.va_mask = AT_ALL;
3736      -                vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3737      -        } else
3738      -                vap = NULL;
3739      -#else
3740 3422          va.va_mask = AT_ALL;
3741 3423          vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3742      -#endif
3743 3424  
3744 3425          if (vp->v_type != VDIR) {
3745 3426                  error = ENOTDIR;
3746 3427                  goto out;
3747 3428          }
3748 3429  
3749 3430          error = VOP_ACCESS(vp, VREAD, 0, cr, NULL);
3750 3431          if (error)
3751 3432                  goto out;
3752 3433  
3753 3434          /*
3754 3435           * Don't allow arbitrary counts for allocation
3755 3436           */
3756 3437          if (args->maxcount > rfs3_tsize(req))
3757 3438                  args->maxcount = rfs3_tsize(req);
3758 3439  
3759 3440          /*
3760 3441           * Make sure that there is room to read at least one entry
3761 3442           * if any are available
3762 3443           */
3763 3444          args->dircount = MIN(args->dircount, args->maxcount);
3764 3445  
3765 3446          if (args->dircount < DIRENT64_RECLEN(MAXNAMELEN))
3766 3447                  args->dircount = DIRENT64_RECLEN(MAXNAMELEN);
3767 3448  
3768 3449          /*
3769 3450           * This allocation relies on a minimum directory entry
3770 3451           * being roughly 24 bytes.  Therefore, the namlen array
3771 3452           * will have enough space based on the maximum number of
3772 3453           * entries to read.
3773 3454           */
3774 3455          namlen = kmem_alloc(args->dircount, KM_SLEEP);
3775 3456  
3776 3457          space_left = args->dircount;
3777 3458          data = kmem_alloc(args->dircount, KM_SLEEP);
3778 3459          dp = (struct dirent64 *)data;
3779 3460          uio.uio_iov = &iov;
3780 3461          uio.uio_iovcnt = 1;
3781 3462          uio.uio_segflg = UIO_SYSSPACE;
3782 3463          uio.uio_extflg = UIO_COPY_CACHED;
3783 3464          uio.uio_loffset = (offset_t)args->cookie;
3784 3465  
3785 3466          /*
3786 3467           * bufsize is used to keep track of the size of the response as we
3787 3468           * get post op attributes and filehandles for each entry.  This is
3788 3469           * an optimization as the server may have read more entries than will
3789 3470           * fit in the buffer specified by maxcount.  We stop calculating
3790 3471           * post op attributes and filehandles once we have exceeded maxcount.
3791 3472           * This will minimize the effect of truncation.
3792 3473           *
3793 3474           * It is primed with:
3794 3475           *      1 for the status +
3795 3476           *      1 for the dir_attributes.attributes boolean +
3796 3477           *      2 for the cookie verifier
3797 3478           * all times BYTES_PER_XDR_UNIT to convert from XDR units
3798 3479           * to bytes.  If there are directory attributes to be
3799 3480           * returned, then:
3800 3481           *      NFS3_SIZEOF_FATTR3 for the dir_attributes.attr fattr3
3801 3482           * time BYTES_PER_XDR_UNIT is added to account for them.
3802 3483           */
3803 3484          bufsize = (1 + 1 + 2) * BYTES_PER_XDR_UNIT;
3804 3485          if (vap != NULL)
3805 3486                  bufsize += NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT;
3806 3487  
3807 3488  getmoredents:
3808 3489          /*
3809 3490           * Here we make a check so that our read unit is not larger than
3810 3491           * the space left in the buffer.
3811 3492           */
3812 3493          rd_unit = MIN(rd_unit, space_left);
3813 3494          iov.iov_base = (char *)dp;
3814 3495          iov.iov_len = rd_unit;
3815 3496          uio.uio_resid = rd_unit;
3816 3497          prev_len = rd_unit;
3817 3498  
3818 3499          error = VOP_READDIR(vp, &uio, cr, &iseof, NULL, 0);
3819 3500  
3820 3501          if (error) {
3821 3502                  kmem_free(data, args->dircount);
3822 3503                  goto out;
3823 3504          }
3824 3505  
3825 3506          if (uio.uio_resid == prev_len && !iseof) {
3826 3507                  if (nents == 0) {
3827 3508                          kmem_free(data, args->dircount);
3828 3509                          resp->status = NFS3ERR_TOOSMALL;
3829 3510                          goto out1;
3830 3511                  }
3831 3512  
3832 3513                  /*
3833 3514                   * We could not get any more entries, so get the attributes
3834 3515                   * and filehandle for the entries already obtained.
3835 3516                   */
3836 3517                  goto good;
3837 3518          }
3838 3519  
3839 3520          /*
3840 3521           * We estimate the size of the response by assuming the
3841 3522           * entry exists and attributes and filehandle are also valid
3842 3523           */
3843 3524          for (size = prev_len - uio.uio_resid;
3844 3525              size > 0;
3845 3526              size -= dp->d_reclen, dp = nextdp(dp)) {
3846 3527  
3847 3528                  if (dp->d_ino == 0) {
3848 3529                          nents++;
3849 3530                          continue;
3850 3531                  }
3851 3532  
3852 3533                  namlen[nents] = strlen(dp->d_name);
3853 3534                  entrysize = NFS3_READDIRPLUS_ENTRY(namlen[nents]);
3854 3535  
3855 3536                  /*
3856 3537                   * We need to check to see if the number of bytes left
3857 3538                   * to go into the buffer will actually fit into the
3858 3539                   * buffer.  This is calculated as the size of this
3859 3540                   * entry plus:
3860 3541                   *      1 for the true/false list indicator +
3861 3542                   *      1 for the eof indicator
3862 3543                   * times BYTES_PER_XDR_UNIT to convert from XDR units
3863 3544                   * to bytes.
3864 3545                   *
3865 3546                   * Also check the dircount limit against the first entry read
3866 3547                   *
3867 3548                   */
3868 3549                  tofit = entrysize + (1 + 1) * BYTES_PER_XDR_UNIT;
3869 3550                  if (bufsize + tofit > args->maxcount) {
3870 3551                          /*
3871 3552                           * We make a check here to see if this was the
3872 3553                           * first entry being measured.  If so, then maxcount
3873 3554                           * was too small to begin with and so we need to
3874 3555                           * return with NFS3ERR_TOOSMALL.
3875 3556                           */
3876 3557                          if (nents == 0) {
3877 3558                                  kmem_free(data, args->dircount);
3878 3559                                  resp->status = NFS3ERR_TOOSMALL;
3879 3560                                  goto out1;
3880 3561                          }
3881 3562                          iseof = FALSE;
3882 3563                          goto good;
3883 3564                  }
3884 3565                  bufsize += entrysize;
3885 3566                  nents++;
3886 3567          }
3887 3568  
3888 3569          /*
3889 3570           * If there is enough room to fit at least 1 more entry including
3890 3571           * post op attributes and filehandle in the buffer AND that we haven't
  
    | ↓ open down ↓ | 138 lines elided | ↑ open up ↑ | 
3891 3572           * exceeded dircount then go back and get some more.
3892 3573           */
3893 3574          if (!iseof &&
3894 3575              (args->maxcount - bufsize) >= NFS3_READDIRPLUS_ENTRY(MAXNAMELEN)) {
3895 3576                  space_left -= (prev_len - uio.uio_resid);
3896 3577                  if (space_left >= DIRENT64_RECLEN(MAXNAMELEN))
3897 3578                          goto getmoredents;
3898 3579  
3899 3580                  /* else, fall through */
3900 3581          }
3901      -
3902 3582  good:
3903      -
3904      -#ifdef DEBUG
3905      -        if (rfs3_do_post_op_attr) {
3906      -                va.va_mask = AT_ALL;
3907      -                vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3908      -        } else
3909      -                vap = NULL;
3910      -#else
3911 3583          va.va_mask = AT_ALL;
3912 3584          vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
3913      -#endif
3914 3585  
3915 3586          VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
3916 3587  
3917 3588          infop = kmem_alloc(nents * sizeof (struct entryplus3_info), KM_SLEEP);
3918 3589          resp->resok.infop = infop;
3919 3590  
3920 3591          dp = (struct dirent64 *)data;
3921 3592          for (i = 0; i < nents; i++) {
3922 3593  
3923 3594                  if (dp->d_ino == 0) {
3924 3595                          infop[i].attr.attributes = FALSE;
3925 3596                          infop[i].fh.handle_follows = FALSE;
3926 3597                          dp = nextdp(dp);
3927 3598                          continue;
3928 3599                  }
3929 3600  
3930 3601                  infop[i].namelen = namlen[i];
  
    | ↓ open down ↓ | 7 lines elided | ↑ open up ↑ | 
3931 3602  
3932 3603                  error = VOP_LOOKUP(vp, dp->d_name, &nvp, NULL, 0, NULL, cr,
3933 3604                      NULL, NULL, NULL);
3934 3605                  if (error) {
3935 3606                          infop[i].attr.attributes = FALSE;
3936 3607                          infop[i].fh.handle_follows = FALSE;
3937 3608                          dp = nextdp(dp);
3938 3609                          continue;
3939 3610                  }
3940 3611  
3941      -#ifdef DEBUG
3942      -                if (rfs3_do_post_op_attr) {
3943      -                        nva.va_mask = AT_ALL;
3944      -                        nvap = rfs4_delegated_getattr(nvp, &nva, 0, cr) ?
3945      -                            NULL : &nva;
3946      -                } else
3947      -                        nvap = NULL;
3948      -#else
3949 3612                  nva.va_mask = AT_ALL;
3950 3613                  nvap = rfs4_delegated_getattr(nvp, &nva, 0, cr) ? NULL : &nva;
3951      -#endif
     3614 +
3952 3615                  /* Lie about the object type for a referral */
3953 3616                  if (vn_is_nfs_reparse(nvp, cr))
3954 3617                          nvap->va_type = VLNK;
3955 3618  
3956      -                vattr_to_post_op_attr(nvap, &infop[i].attr);
3957      -
3958      -#ifdef DEBUG
3959      -                if (!rfs3_do_post_op_fh3)
3960      -                        infop[i].fh.handle_follows = FALSE;
3961      -                else {
3962      -#endif
3963      -                error = makefh3(&infop[i].fh.handle, nvp, exi);
3964      -                if (!error)
3965      -                        infop[i].fh.handle_follows = TRUE;
3966      -                else
     3619 +                if (vn_ismntpt(nvp)) {
     3620 +                        infop[i].attr.attributes = FALSE;
3967 3621                          infop[i].fh.handle_follows = FALSE;
3968      -#ifdef DEBUG
     3622 +                } else {
     3623 +                        vattr_to_post_op_attr(nvap, &infop[i].attr);
     3624 +
     3625 +                        error = makefh3(&infop[i].fh.handle, nvp, exi);
     3626 +                        if (!error)
     3627 +                                infop[i].fh.handle_follows = TRUE;
     3628 +                        else
     3629 +                                infop[i].fh.handle_follows = FALSE;
3969 3630                  }
3970      -#endif
3971 3631  
3972 3632                  VN_RELE(nvp);
3973 3633                  dp = nextdp(dp);
3974 3634          }
3975 3635  
3976 3636          ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf;
3977 3637          ret = nfscmd_convdirplus(ca, exi, data, nents, args->dircount, &ndata);
3978 3638          if (ndata == NULL)
3979 3639                  ndata = data;
3980 3640  
3981 3641          if (ret > 0) {
3982 3642                  /*
3983 3643                   * We had to drop one or more entries in order to fit
3984 3644                   * during the character conversion.  We need to patch
3985 3645                   * up the size and eof info.
3986 3646                   */
3987 3647                  if (iseof)
3988 3648                          iseof = FALSE;
3989 3649  
3990 3650                  ret = nfscmd_dropped_entrysize((struct dirent64 *)data,
3991 3651                      nents, ret);
3992 3652          }
3993 3653  
3994 3654  
3995 3655  #if 0 /* notyet */
3996 3656          /*
3997 3657           * Don't do this.  It causes local disk writes when just
3998 3658           * reading the file and the overhead is deemed larger
3999 3659           * than the benefit.
4000 3660           */
4001 3661          /*
4002 3662           * Force modified metadata out to stable storage.
4003 3663           */
4004 3664          (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
4005 3665  #endif
4006 3666  
4007 3667          kmem_free(namlen, args->dircount);
4008 3668  
4009 3669          resp->status = NFS3_OK;
4010 3670          vattr_to_post_op_attr(vap, &resp->resok.dir_attributes);
4011 3671          resp->resok.cookieverf = 0;
4012 3672          resp->resok.reply.entries = (entryplus3 *)ndata;
4013 3673          resp->resok.reply.eof = iseof;
4014 3674          resp->resok.size = nents;
4015 3675          resp->resok.count = args->dircount - ret;
4016 3676          resp->resok.maxcount = args->maxcount;
4017 3677  
4018 3678          DTRACE_NFSV3_4(op__readdirplus__done, struct svc_req *, req,
4019 3679              cred_t *, cr, vnode_t *, vp, READDIRPLUS3res *, resp);
4020 3680          if (ndata != data)
4021 3681                  kmem_free(data, args->dircount);
4022 3682  
4023 3683  
4024 3684          VN_RELE(vp);
4025 3685  
4026 3686          return;
4027 3687  
4028 3688  out:
4029 3689          if (curthread->t_flag & T_WOULDBLOCK) {
4030 3690                  curthread->t_flag &= ~T_WOULDBLOCK;
4031 3691                  resp->status = NFS3ERR_JUKEBOX;
4032 3692          } else {
4033 3693                  resp->status = puterrno3(error);
4034 3694          }
4035 3695  out1:
4036 3696          DTRACE_NFSV3_4(op__readdirplus__done, struct svc_req *, req,
4037 3697              cred_t *, cr, vnode_t *, vp, READDIRPLUS3res *, resp);
4038 3698  
4039 3699          if (vp != NULL) {
4040 3700                  VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
4041 3701                  VN_RELE(vp);
4042 3702          }
4043 3703  
4044 3704          if (namlen != NULL)
4045 3705                  kmem_free(namlen, args->dircount);
4046 3706  
4047 3707          vattr_to_post_op_attr(vap, &resp->resfail.dir_attributes);
4048 3708  }
4049 3709  
4050 3710  void *
4051 3711  rfs3_readdirplus_getfh(READDIRPLUS3args *args)
4052 3712  {
4053 3713  
4054 3714          return (&args->dir);
4055 3715  }
4056 3716  
4057 3717  void
4058 3718  rfs3_readdirplus_free(READDIRPLUS3res *resp)
4059 3719  {
4060 3720  
4061 3721          if (resp->status == NFS3_OK) {
4062 3722                  kmem_free(resp->resok.reply.entries, resp->resok.count);
4063 3723                  kmem_free(resp->resok.infop,
4064 3724                      resp->resok.size * sizeof (struct entryplus3_info));
4065 3725          }
4066 3726  }
4067 3727  
4068 3728  /* ARGSUSED */
4069 3729  void
4070 3730  rfs3_fsstat(FSSTAT3args *args, FSSTAT3res *resp, struct exportinfo *exi,
4071 3731          struct svc_req *req, cred_t *cr)
4072 3732  {
4073 3733          int error;
4074 3734          vnode_t *vp;
4075 3735          struct vattr *vap;
4076 3736          struct vattr va;
4077 3737          struct statvfs64 sb;
4078 3738  
4079 3739          vap = NULL;
4080 3740  
4081 3741          vp = nfs3_fhtovp(&args->fsroot, exi);
4082 3742  
4083 3743          DTRACE_NFSV3_4(op__fsstat__start, struct svc_req *, req,
4084 3744              cred_t *, cr, vnode_t *, vp, FSSTAT3args *, args);
4085 3745  
4086 3746          if (vp == NULL) {
4087 3747                  error = ESTALE;
4088 3748                  goto out;
4089 3749          }
4090 3750  
4091 3751          if (is_system_labeled()) {
4092 3752                  bslabel_t *clabel = req->rq_label;
4093 3753  
4094 3754                  ASSERT(clabel != NULL);
4095 3755                  DTRACE_PROBE2(tx__rfs3__log__info__opfsstat__clabel, char *,
4096 3756                      "got client label from request(1)", struct svc_req *, req);
4097 3757  
4098 3758                  if (!blequal(&l_admin_low->tsl_label, clabel)) {
  
    | ↓ open down ↓ | 118 lines elided | ↑ open up ↑ | 
4099 3759                          if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
4100 3760                              exi)) {
4101 3761                                  resp->status = NFS3ERR_ACCES;
4102 3762                                  goto out1;
4103 3763                          }
4104 3764                  }
4105 3765          }
4106 3766  
4107 3767          error = VFS_STATVFS(vp->v_vfsp, &sb);
4108 3768  
4109      -#ifdef DEBUG
4110      -        if (rfs3_do_post_op_attr) {
4111      -                va.va_mask = AT_ALL;
4112      -                vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
4113      -        } else
4114      -                vap = NULL;
4115      -#else
4116 3769          va.va_mask = AT_ALL;
4117 3770          vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
4118      -#endif
4119 3771  
4120 3772          if (error)
4121 3773                  goto out;
4122 3774  
4123 3775          resp->status = NFS3_OK;
4124 3776          vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
4125 3777          if (sb.f_blocks != (fsblkcnt64_t)-1)
4126 3778                  resp->resok.tbytes = (size3)sb.f_frsize * (size3)sb.f_blocks;
4127 3779          else
4128 3780                  resp->resok.tbytes = (size3)sb.f_blocks;
4129 3781          if (sb.f_bfree != (fsblkcnt64_t)-1)
4130 3782                  resp->resok.fbytes = (size3)sb.f_frsize * (size3)sb.f_bfree;
4131 3783          else
4132 3784                  resp->resok.fbytes = (size3)sb.f_bfree;
4133 3785          if (sb.f_bavail != (fsblkcnt64_t)-1)
4134 3786                  resp->resok.abytes = (size3)sb.f_frsize * (size3)sb.f_bavail;
4135 3787          else
4136 3788                  resp->resok.abytes = (size3)sb.f_bavail;
4137 3789          resp->resok.tfiles = (size3)sb.f_files;
4138 3790          resp->resok.ffiles = (size3)sb.f_ffree;
4139 3791          resp->resok.afiles = (size3)sb.f_favail;
4140 3792          resp->resok.invarsec = 0;
4141 3793  
4142 3794          DTRACE_NFSV3_4(op__fsstat__done, struct svc_req *, req,
4143 3795              cred_t *, cr, vnode_t *, vp, FSSTAT3res *, resp);
4144 3796          VN_RELE(vp);
4145 3797  
4146 3798          return;
4147 3799  
4148 3800  out:
4149 3801          if (curthread->t_flag & T_WOULDBLOCK) {
4150 3802                  curthread->t_flag &= ~T_WOULDBLOCK;
4151 3803                  resp->status = NFS3ERR_JUKEBOX;
4152 3804          } else
4153 3805                  resp->status = puterrno3(error);
4154 3806  out1:
4155 3807          DTRACE_NFSV3_4(op__fsstat__done, struct svc_req *, req,
4156 3808              cred_t *, cr, vnode_t *, vp, FSSTAT3res *, resp);
4157 3809  
4158 3810          if (vp != NULL)
4159 3811                  VN_RELE(vp);
4160 3812          vattr_to_post_op_attr(vap, &resp->resfail.obj_attributes);
4161 3813  }
4162 3814  
4163 3815  void *
4164 3816  rfs3_fsstat_getfh(FSSTAT3args *args)
4165 3817  {
4166 3818  
4167 3819          return (&args->fsroot);
4168 3820  }
4169 3821  
4170 3822  void
4171 3823  rfs3_fsinfo(FSINFO3args *args, FSINFO3res *resp, struct exportinfo *exi,
4172 3824          struct svc_req *req, cred_t *cr)
4173 3825  {
4174 3826          vnode_t *vp;
4175 3827          struct vattr *vap;
4176 3828          struct vattr va;
4177 3829          uint32_t xfer_size;
4178 3830          ulong_t l = 0;
4179 3831          int error;
4180 3832  
4181 3833          vp = nfs3_fhtovp(&args->fsroot, exi);
4182 3834  
4183 3835          DTRACE_NFSV3_4(op__fsinfo__start, struct svc_req *, req,
4184 3836              cred_t *, cr, vnode_t *, vp, FSINFO3args *, args);
4185 3837  
4186 3838          if (vp == NULL) {
4187 3839                  if (curthread->t_flag & T_WOULDBLOCK) {
4188 3840                          curthread->t_flag &= ~T_WOULDBLOCK;
4189 3841                          resp->status = NFS3ERR_JUKEBOX;
4190 3842                  } else
4191 3843                          resp->status = NFS3ERR_STALE;
4192 3844                  vattr_to_post_op_attr(NULL, &resp->resfail.obj_attributes);
4193 3845                  goto out;
4194 3846          }
4195 3847  
4196 3848          if (is_system_labeled()) {
4197 3849                  bslabel_t *clabel = req->rq_label;
4198 3850  
4199 3851                  ASSERT(clabel != NULL);
4200 3852                  DTRACE_PROBE2(tx__rfs3__log__info__opfsinfo__clabel, char *,
4201 3853                      "got client label from request(1)", struct svc_req *, req);
4202 3854  
4203 3855                  if (!blequal(&l_admin_low->tsl_label, clabel)) {
  
    | ↓ open down ↓ | 75 lines elided | ↑ open up ↑ | 
4204 3856                          if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
4205 3857                              exi)) {
4206 3858                                  resp->status = NFS3ERR_STALE;
4207 3859                                  vattr_to_post_op_attr(NULL,
4208 3860                                      &resp->resfail.obj_attributes);
4209 3861                                  goto out;
4210 3862                          }
4211 3863                  }
4212 3864          }
4213 3865  
4214      -#ifdef DEBUG
4215      -        if (rfs3_do_post_op_attr) {
4216      -                va.va_mask = AT_ALL;
4217      -                vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
4218      -        } else
4219      -                vap = NULL;
4220      -#else
4221 3866          va.va_mask = AT_ALL;
4222 3867          vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
4223      -#endif
4224 3868  
4225 3869          resp->status = NFS3_OK;
4226 3870          vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
4227 3871          xfer_size = rfs3_tsize(req);
4228 3872          resp->resok.rtmax = xfer_size;
4229 3873          resp->resok.rtpref = xfer_size;
4230 3874          resp->resok.rtmult = DEV_BSIZE;
4231 3875          resp->resok.wtmax = xfer_size;
4232 3876          resp->resok.wtpref = xfer_size;
4233 3877          resp->resok.wtmult = DEV_BSIZE;
4234 3878          resp->resok.dtpref = MAXBSIZE;
4235 3879  
4236 3880          /*
4237 3881           * Large file spec: want maxfilesize based on limit of
4238 3882           * underlying filesystem.  We can guess 2^31-1 if need be.
4239 3883           */
4240 3884          error = VOP_PATHCONF(vp, _PC_FILESIZEBITS, &l, cr, NULL);
4241 3885          if (error) {
4242 3886                  resp->status = puterrno3(error);
4243 3887                  goto out;
4244 3888          }
4245 3889  
4246 3890          /*
4247 3891           * If the underlying file system does not support _PC_FILESIZEBITS,
4248 3892           * return a reasonable default. Note that error code on VOP_PATHCONF
4249 3893           * will be 0, even if the underlying file system does not support
4250 3894           * _PC_FILESIZEBITS.
4251 3895           */
4252 3896          if (l == (ulong_t)-1) {
4253 3897                  resp->resok.maxfilesize = MAXOFF32_T;
4254 3898          } else {
4255 3899                  if (l >= (sizeof (uint64_t) * 8))
4256 3900                          resp->resok.maxfilesize = INT64_MAX;
4257 3901                  else
4258 3902                          resp->resok.maxfilesize = (1LL << (l-1)) - 1;
4259 3903          }
4260 3904  
4261 3905          resp->resok.time_delta.seconds = 0;
4262 3906          resp->resok.time_delta.nseconds = 1000;
4263 3907          resp->resok.properties = FSF3_LINK | FSF3_SYMLINK |
4264 3908              FSF3_HOMOGENEOUS | FSF3_CANSETTIME;
4265 3909  
4266 3910          DTRACE_NFSV3_4(op__fsinfo__done, struct svc_req *, req,
4267 3911              cred_t *, cr, vnode_t *, vp, FSINFO3res *, resp);
4268 3912  
4269 3913          VN_RELE(vp);
4270 3914  
4271 3915          return;
4272 3916  
4273 3917  out:
4274 3918          DTRACE_NFSV3_4(op__fsinfo__done, struct svc_req *, req,
4275 3919              cred_t *, cr, vnode_t *, NULL, FSINFO3res *, resp);
4276 3920          if (vp != NULL)
4277 3921                  VN_RELE(vp);
4278 3922  }
4279 3923  
4280 3924  void *
4281 3925  rfs3_fsinfo_getfh(FSINFO3args *args)
4282 3926  {
4283 3927  
4284 3928          return (&args->fsroot);
4285 3929  }
4286 3930  
4287 3931  /* ARGSUSED */
4288 3932  void
4289 3933  rfs3_pathconf(PATHCONF3args *args, PATHCONF3res *resp, struct exportinfo *exi,
4290 3934          struct svc_req *req, cred_t *cr)
4291 3935  {
4292 3936          int error;
4293 3937          vnode_t *vp;
4294 3938          struct vattr *vap;
4295 3939          struct vattr va;
4296 3940          ulong_t val;
4297 3941  
4298 3942          vap = NULL;
4299 3943  
4300 3944          vp = nfs3_fhtovp(&args->object, exi);
4301 3945  
4302 3946          DTRACE_NFSV3_4(op__pathconf__start, struct svc_req *, req,
4303 3947              cred_t *, cr, vnode_t *, vp, PATHCONF3args *, args);
4304 3948  
4305 3949          if (vp == NULL) {
4306 3950                  error = ESTALE;
4307 3951                  goto out;
4308 3952          }
4309 3953  
4310 3954          if (is_system_labeled()) {
4311 3955                  bslabel_t *clabel = req->rq_label;
4312 3956  
4313 3957                  ASSERT(clabel != NULL);
4314 3958                  DTRACE_PROBE2(tx__rfs3__log__info__oppathconf__clabel, char *,
4315 3959                      "got client label from request(1)", struct svc_req *, req);
  
    | ↓ open down ↓ | 82 lines elided | ↑ open up ↑ | 
4316 3960  
4317 3961                  if (!blequal(&l_admin_low->tsl_label, clabel)) {
4318 3962                          if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK,
4319 3963                              exi)) {
4320 3964                                  resp->status = NFS3ERR_ACCES;
4321 3965                                  goto out1;
4322 3966                          }
4323 3967                  }
4324 3968          }
4325 3969  
4326      -#ifdef DEBUG
4327      -        if (rfs3_do_post_op_attr) {
4328      -                va.va_mask = AT_ALL;
4329      -                vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
4330      -        } else
4331      -                vap = NULL;
4332      -#else
4333 3970          va.va_mask = AT_ALL;
4334 3971          vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
4335      -#endif
4336 3972  
4337 3973          error = VOP_PATHCONF(vp, _PC_LINK_MAX, &val, cr, NULL);
4338 3974          if (error)
4339 3975                  goto out;
4340 3976          resp->resok.info.link_max = (uint32)val;
4341 3977  
4342 3978          error = VOP_PATHCONF(vp, _PC_NAME_MAX, &val, cr, NULL);
4343 3979          if (error)
4344 3980                  goto out;
4345 3981          resp->resok.info.name_max = (uint32)val;
4346 3982  
4347 3983          error = VOP_PATHCONF(vp, _PC_NO_TRUNC, &val, cr, NULL);
4348 3984          if (error)
4349 3985                  goto out;
4350 3986          if (val == 1)
4351 3987                  resp->resok.info.no_trunc = TRUE;
4352 3988          else
4353 3989                  resp->resok.info.no_trunc = FALSE;
4354 3990  
4355 3991          error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &val, cr, NULL);
4356 3992          if (error)
4357 3993                  goto out;
4358 3994          if (val == 1)
4359 3995                  resp->resok.info.chown_restricted = TRUE;
4360 3996          else
4361 3997                  resp->resok.info.chown_restricted = FALSE;
4362 3998  
4363 3999          resp->status = NFS3_OK;
4364 4000          vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
4365 4001          resp->resok.info.case_insensitive = FALSE;
4366 4002          resp->resok.info.case_preserving = TRUE;
4367 4003          DTRACE_NFSV3_4(op__pathconf__done, struct svc_req *, req,
4368 4004              cred_t *, cr, vnode_t *, vp, PATHCONF3res *, resp);
4369 4005          VN_RELE(vp);
4370 4006          return;
4371 4007  
4372 4008  out:
4373 4009          if (curthread->t_flag & T_WOULDBLOCK) {
4374 4010                  curthread->t_flag &= ~T_WOULDBLOCK;
4375 4011                  resp->status = NFS3ERR_JUKEBOX;
4376 4012          } else
4377 4013                  resp->status = puterrno3(error);
4378 4014  out1:
4379 4015          DTRACE_NFSV3_4(op__pathconf__done, struct svc_req *, req,
4380 4016              cred_t *, cr, vnode_t *, vp, PATHCONF3res *, resp);
4381 4017          if (vp != NULL)
4382 4018                  VN_RELE(vp);
4383 4019          vattr_to_post_op_attr(vap, &resp->resfail.obj_attributes);
4384 4020  }
4385 4021  
4386 4022  void *
4387 4023  rfs3_pathconf_getfh(PATHCONF3args *args)
4388 4024  {
4389 4025  
4390 4026          return (&args->object);
4391 4027  }
4392 4028  
4393 4029  void
4394 4030  rfs3_commit(COMMIT3args *args, COMMIT3res *resp, struct exportinfo *exi,
4395 4031          struct svc_req *req, cred_t *cr)
4396 4032  {
4397 4033          int error;
4398 4034          vnode_t *vp;
4399 4035          struct vattr *bvap;
4400 4036          struct vattr bva;
4401 4037          struct vattr *avap;
4402 4038          struct vattr ava;
4403 4039  
4404 4040          bvap = NULL;
4405 4041          avap = NULL;
4406 4042  
4407 4043          vp = nfs3_fhtovp(&args->file, exi);
4408 4044  
4409 4045          DTRACE_NFSV3_4(op__commit__start, struct svc_req *, req,
4410 4046              cred_t *, cr, vnode_t *, vp, COMMIT3args *, args);
4411 4047  
4412 4048          if (vp == NULL) {
4413 4049                  error = ESTALE;
4414 4050                  goto out;
4415 4051          }
4416 4052  
  
    | ↓ open down ↓ | 71 lines elided | ↑ open up ↑ | 
4417 4053          bva.va_mask = AT_ALL;
4418 4054          error = VOP_GETATTR(vp, &bva, 0, cr, NULL);
4419 4055  
4420 4056          /*
4421 4057           * If we can't get the attributes, then we can't do the
4422 4058           * right access checking.  So, we'll fail the request.
4423 4059           */
4424 4060          if (error)
4425 4061                  goto out;
4426 4062  
4427      -#ifdef DEBUG
4428      -        if (rfs3_do_pre_op_attr)
4429      -                bvap = &bva;
4430      -        else
4431      -                bvap = NULL;
4432      -#else
4433 4063          bvap = &bva;
4434      -#endif
4435 4064  
4436 4065          if (rdonly(exi, req)) {
4437 4066                  resp->status = NFS3ERR_ROFS;
4438 4067                  goto out1;
4439 4068          }
4440 4069  
4441 4070          if (vp->v_type != VREG) {
4442 4071                  resp->status = NFS3ERR_INVAL;
4443 4072                  goto out1;
4444 4073          }
4445 4074  
4446 4075          if (is_system_labeled()) {
4447 4076                  bslabel_t *clabel = req->rq_label;
4448 4077  
4449 4078                  ASSERT(clabel != NULL);
4450 4079                  DTRACE_PROBE2(tx__rfs3__log__info__opcommit__clabel, char *,
4451 4080                      "got client label from request(1)", struct svc_req *, req);
4452 4081  
4453 4082                  if (!blequal(&l_admin_low->tsl_label, clabel)) {
4454 4083                          if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK,
4455 4084                              exi)) {
4456 4085                                  resp->status = NFS3ERR_ACCES;
4457 4086                                  goto out1;
  
    | ↓ open down ↓ | 13 lines elided | ↑ open up ↑ | 
4458 4087                          }
4459 4088                  }
4460 4089          }
4461 4090  
4462 4091          if (crgetuid(cr) != bva.va_uid &&
4463 4092              (error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL)))
4464 4093                  goto out;
4465 4094  
4466 4095          error = VOP_FSYNC(vp, FSYNC, cr, NULL);
4467 4096  
4468      -#ifdef DEBUG
4469      -        if (rfs3_do_post_op_attr) {
4470      -                ava.va_mask = AT_ALL;
4471      -                avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
4472      -        } else
4473      -                avap = NULL;
4474      -#else
4475 4097          ava.va_mask = AT_ALL;
4476 4098          avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava;
4477      -#endif
4478 4099  
4479 4100          if (error)
4480 4101                  goto out;
4481 4102  
4482 4103          resp->status = NFS3_OK;
4483 4104          vattr_to_wcc_data(bvap, avap, &resp->resok.file_wcc);
4484 4105          resp->resok.verf = write3verf;
4485 4106  
4486 4107          DTRACE_NFSV3_4(op__commit__done, struct svc_req *, req,
4487 4108              cred_t *, cr, vnode_t *, vp, COMMIT3res *, resp);
4488 4109  
4489 4110          VN_RELE(vp);
4490 4111  
4491 4112          return;
4492 4113  
4493 4114  out:
4494 4115          if (curthread->t_flag & T_WOULDBLOCK) {
4495 4116                  curthread->t_flag &= ~T_WOULDBLOCK;
4496 4117                  resp->status = NFS3ERR_JUKEBOX;
4497 4118          } else
4498 4119                  resp->status = puterrno3(error);
4499 4120  out1:
4500 4121          DTRACE_NFSV3_4(op__commit__done, struct svc_req *, req,
4501 4122              cred_t *, cr, vnode_t *, vp, COMMIT3res *, resp);
4502 4123  
4503 4124          if (vp != NULL)
4504 4125                  VN_RELE(vp);
4505 4126          vattr_to_wcc_data(bvap, avap, &resp->resfail.file_wcc);
4506 4127  }
4507 4128  
4508 4129  void *
4509 4130  rfs3_commit_getfh(COMMIT3args *args)
4510 4131  {
4511 4132  
4512 4133          return (&args->file);
4513 4134  }
4514 4135  
4515 4136  static int
4516 4137  sattr3_to_vattr(sattr3 *sap, struct vattr *vap)
4517 4138  {
4518 4139  
4519 4140          vap->va_mask = 0;
4520 4141  
4521 4142          if (sap->mode.set_it) {
4522 4143                  vap->va_mode = (mode_t)sap->mode.mode;
4523 4144                  vap->va_mask |= AT_MODE;
4524 4145          }
4525 4146          if (sap->uid.set_it) {
4526 4147                  vap->va_uid = (uid_t)sap->uid.uid;
4527 4148                  vap->va_mask |= AT_UID;
4528 4149          }
4529 4150          if (sap->gid.set_it) {
4530 4151                  vap->va_gid = (gid_t)sap->gid.gid;
4531 4152                  vap->va_mask |= AT_GID;
4532 4153          }
4533 4154          if (sap->size.set_it) {
4534 4155                  if (sap->size.size > (size3)((u_longlong_t)-1))
4535 4156                          return (EINVAL);
4536 4157                  vap->va_size = sap->size.size;
4537 4158                  vap->va_mask |= AT_SIZE;
4538 4159          }
4539 4160          if (sap->atime.set_it == SET_TO_CLIENT_TIME) {
4540 4161  #ifndef _LP64
4541 4162                  /* check time validity */
4542 4163                  if (!NFS3_TIME_OK(sap->atime.atime.seconds))
4543 4164                          return (EOVERFLOW);
4544 4165  #endif
4545 4166                  /*
4546 4167                   * nfs protocol defines times as unsigned so don't extend sign,
4547 4168                   * unless sysadmin set nfs_allow_preepoch_time.
4548 4169                   */
4549 4170                  NFS_TIME_T_CONVERT(vap->va_atime.tv_sec,
4550 4171                      sap->atime.atime.seconds);
4551 4172                  vap->va_atime.tv_nsec = (uint32_t)sap->atime.atime.nseconds;
4552 4173                  vap->va_mask |= AT_ATIME;
4553 4174          } else if (sap->atime.set_it == SET_TO_SERVER_TIME) {
4554 4175                  gethrestime(&vap->va_atime);
4555 4176                  vap->va_mask |= AT_ATIME;
4556 4177          }
4557 4178          if (sap->mtime.set_it == SET_TO_CLIENT_TIME) {
4558 4179  #ifndef _LP64
4559 4180                  /* check time validity */
4560 4181                  if (!NFS3_TIME_OK(sap->mtime.mtime.seconds))
4561 4182                          return (EOVERFLOW);
4562 4183  #endif
4563 4184                  /*
4564 4185                   * nfs protocol defines times as unsigned so don't extend sign,
4565 4186                   * unless sysadmin set nfs_allow_preepoch_time.
4566 4187                   */
4567 4188                  NFS_TIME_T_CONVERT(vap->va_mtime.tv_sec,
4568 4189                      sap->mtime.mtime.seconds);
4569 4190                  vap->va_mtime.tv_nsec = (uint32_t)sap->mtime.mtime.nseconds;
4570 4191                  vap->va_mask |= AT_MTIME;
4571 4192          } else if (sap->mtime.set_it == SET_TO_SERVER_TIME) {
4572 4193                  gethrestime(&vap->va_mtime);
4573 4194                  vap->va_mask |= AT_MTIME;
4574 4195          }
4575 4196  
4576 4197          return (0);
4577 4198  }
4578 4199  
4579 4200  static ftype3 vt_to_nf3[] = {
4580 4201          0, NF3REG, NF3DIR, NF3BLK, NF3CHR, NF3LNK, NF3FIFO, 0, 0, NF3SOCK, 0
4581 4202  };
4582 4203  
4583 4204  static int
4584 4205  vattr_to_fattr3(struct vattr *vap, fattr3 *fap)
4585 4206  {
4586 4207  
4587 4208          ASSERT(vap->va_type >= VNON && vap->va_type <= VBAD);
4588 4209          /* Return error if time or size overflow */
4589 4210          if (! (NFS_VAP_TIME_OK(vap) && NFS3_SIZE_OK(vap->va_size))) {
4590 4211                  return (EOVERFLOW);
4591 4212          }
4592 4213          fap->type = vt_to_nf3[vap->va_type];
4593 4214          fap->mode = (mode3)(vap->va_mode & MODEMASK);
4594 4215          fap->nlink = (uint32)vap->va_nlink;
4595 4216          if (vap->va_uid == UID_NOBODY)
4596 4217                  fap->uid = (uid3)NFS_UID_NOBODY;
4597 4218          else
4598 4219                  fap->uid = (uid3)vap->va_uid;
4599 4220          if (vap->va_gid == GID_NOBODY)
4600 4221                  fap->gid = (gid3)NFS_GID_NOBODY;
4601 4222          else
4602 4223                  fap->gid = (gid3)vap->va_gid;
4603 4224          fap->size = (size3)vap->va_size;
4604 4225          fap->used = (size3)DEV_BSIZE * (size3)vap->va_nblocks;
4605 4226          fap->rdev.specdata1 = (uint32)getmajor(vap->va_rdev);
4606 4227          fap->rdev.specdata2 = (uint32)getminor(vap->va_rdev);
4607 4228          fap->fsid = (uint64)vap->va_fsid;
4608 4229          fap->fileid = (fileid3)vap->va_nodeid;
4609 4230          fap->atime.seconds = vap->va_atime.tv_sec;
4610 4231          fap->atime.nseconds = vap->va_atime.tv_nsec;
4611 4232          fap->mtime.seconds = vap->va_mtime.tv_sec;
4612 4233          fap->mtime.nseconds = vap->va_mtime.tv_nsec;
4613 4234          fap->ctime.seconds = vap->va_ctime.tv_sec;
4614 4235          fap->ctime.nseconds = vap->va_ctime.tv_nsec;
4615 4236          return (0);
4616 4237  }
4617 4238  
4618 4239  static int
4619 4240  vattr_to_wcc_attr(struct vattr *vap, wcc_attr *wccap)
4620 4241  {
4621 4242  
4622 4243          /* Return error if time or size overflow */
4623 4244          if (!(NFS_TIME_T_OK(vap->va_mtime.tv_sec) &&
4624 4245              NFS_TIME_T_OK(vap->va_ctime.tv_sec) &&
4625 4246              NFS3_SIZE_OK(vap->va_size))) {
4626 4247                  return (EOVERFLOW);
4627 4248          }
4628 4249          wccap->size = (size3)vap->va_size;
4629 4250          wccap->mtime.seconds = vap->va_mtime.tv_sec;
4630 4251          wccap->mtime.nseconds = vap->va_mtime.tv_nsec;
4631 4252          wccap->ctime.seconds = vap->va_ctime.tv_sec;
4632 4253          wccap->ctime.nseconds = vap->va_ctime.tv_nsec;
4633 4254          return (0);
4634 4255  }
4635 4256  
4636 4257  static void
4637 4258  vattr_to_pre_op_attr(struct vattr *vap, pre_op_attr *poap)
4638 4259  {
4639 4260  
4640 4261          /* don't return attrs if time overflow */
4641 4262          if ((vap != NULL) && !vattr_to_wcc_attr(vap, &poap->attr)) {
4642 4263                  poap->attributes = TRUE;
4643 4264          } else
4644 4265                  poap->attributes = FALSE;
4645 4266  }
4646 4267  
4647 4268  void
4648 4269  vattr_to_post_op_attr(struct vattr *vap, post_op_attr *poap)
4649 4270  {
4650 4271  
4651 4272          /* don't return attrs if time overflow */
4652 4273          if ((vap != NULL) && !vattr_to_fattr3(vap, &poap->attr)) {
4653 4274                  poap->attributes = TRUE;
4654 4275          } else
4655 4276                  poap->attributes = FALSE;
4656 4277  }
4657 4278  
4658 4279  static void
4659 4280  vattr_to_wcc_data(struct vattr *bvap, struct vattr *avap, wcc_data *wccp)
4660 4281  {
4661 4282  
4662 4283          vattr_to_pre_op_attr(bvap, &wccp->before);
4663 4284          vattr_to_post_op_attr(avap, &wccp->after);
4664 4285  }
4665 4286  
4666 4287  void
4667 4288  rfs3_srvrinit(void)
4668 4289  {
4669 4290          struct rfs3_verf_overlay {
4670 4291                  uint_t id; /* a "unique" identifier */
4671 4292                  int ts; /* a unique timestamp */
4672 4293          } *verfp;
4673 4294          timestruc_t now;
4674 4295  
4675 4296          /*
4676 4297           * The following algorithm attempts to find a unique verifier
4677 4298           * to be used as the write verifier returned from the server
4678 4299           * to the client.  It is important that this verifier change
4679 4300           * whenever the server reboots.  Of secondary importance, it
4680 4301           * is important for the verifier to be unique between two
4681 4302           * different servers.
4682 4303           *
4683 4304           * Thus, an attempt is made to use the system hostid and the
4684 4305           * current time in seconds when the nfssrv kernel module is
4685 4306           * loaded.  It is assumed that an NFS server will not be able
4686 4307           * to boot and then to reboot in less than a second.  If the
4687 4308           * hostid has not been set, then the current high resolution
4688 4309           * time is used.  This will ensure different verifiers each
4689 4310           * time the server reboots and minimize the chances that two
4690 4311           * different servers will have the same verifier.
4691 4312           */
4692 4313  
4693 4314  #ifndef lint
4694 4315          /*
4695 4316           * We ASSERT that this constant logic expression is
4696 4317           * always true because in the past, it wasn't.
4697 4318           */
4698 4319          ASSERT(sizeof (*verfp) <= sizeof (write3verf));
4699 4320  #endif
4700 4321  
4701 4322          gethrestime(&now);
4702 4323          verfp = (struct rfs3_verf_overlay *)&write3verf;
4703 4324          verfp->ts = (int)now.tv_sec;
4704 4325          verfp->id = zone_get_hostid(NULL);
4705 4326  
4706 4327          if (verfp->id == 0)
4707 4328                  verfp->id = (uint_t)now.tv_nsec;
4708 4329  
4709 4330          nfs3_srv_caller_id = fs_new_caller_id();
4710 4331  
4711 4332  }
4712 4333  
4713 4334  static int
4714 4335  rdma_setup_read_data3(READ3args *args, READ3resok *rok)
4715 4336  {
4716 4337          struct clist    *wcl;
4717 4338          int             wlist_len;
4718 4339          count3          count = rok->count;
4719 4340  
4720 4341          wcl = args->wlist;
4721 4342          if (rdma_setup_read_chunks(wcl, count, &wlist_len) == FALSE) {
4722 4343                  return (FALSE);
4723 4344          }
4724 4345  
4725 4346          wcl = args->wlist;
4726 4347          rok->wlist_len = wlist_len;
4727 4348          rok->wlist = wcl;
4728 4349          return (TRUE);
4729 4350  }
4730 4351  
4731 4352  void
4732 4353  rfs3_srvrfini(void)
4733 4354  {
4734 4355          /* Nothing to do */
4735 4356  }
  
    | ↓ open down ↓ | 248 lines elided | ↑ open up ↑ | 
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX