Print this page
    
Be far more judicious in the use of curzone-using macros.
(Merge and extra asserts by danmcd.)
Try to remove assumption that zone's root vnode is marked VROOT
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/fs/nfs/nfs4_srv_attr.c
          +++ new/usr/src/uts/common/fs/nfs/nfs4_srv_attr.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  /*
  23   23   * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
  25   25   */
  26   26  
  27   27  /*
  28   28   * Copyright 2018 Nexenta Systems, Inc.
  29   29   */
  30   30  
  31   31  #include <sys/systm.h>
  32   32  #include <sys/cmn_err.h>
  33   33  #include <nfs/nfs.h>
  34   34  #include <nfs/export.h>
  35   35  #include <nfs/nfs4.h>
  36   36  #include <sys/ddi.h>
  37   37  #include <sys/door.h>
  38   38  #include <sys/sdt.h>
  39   39  #include <nfs/nfssys.h>
  40   40  
  41   41  void    rfs4_init_compound_state(struct compound_state *);
  42   42  
  43   43  bitmap4 rfs4_supported_attrs;
  44   44  int MSG_PRT_DEBUG = FALSE;
  45   45  
  46   46  /* If building with DEBUG enabled, enable mandattr tunable by default */
  47   47  #ifdef DEBUG
  48   48  #ifndef RFS4_SUPPORT_MANDATTR_ONLY
  49   49  #define RFS4_SUPPORT_MANDATTR_ONLY
  50   50  #endif
  51   51  #endif
  52   52  
  53   53  /*
  54   54   * If building with mandattr only code, disable it by default.
  55   55   * To enable, set rfs4_mandattr_only in /etc/system and reboot.
  56   56   * When building without mandattr ifdef, the compiler should
  57   57   * optimize away the the comparisons because RFS4_MANDATTR_ONLY
  58   58   * is defined to be 0.
  59   59   */
  60   60  #ifdef RFS4_SUPPORT_MANDATTR_ONLY
  61   61  #define NFS4_LAST_MANDATTR FATTR4_RDATTR_ERROR
  62   62  #define RFS4_MANDATTR_ONLY rfs4_mandattr_only
  63   63  int rfs4_mandattr_only = 0;
  64   64  #else
  65   65  #define RFS4_MANDATTR_ONLY 0
  66   66  #endif
  67   67  
  68   68  
  69   69  static void rfs4_ntov_init(void);
  70   70  static int rfs4_fattr4_supported_attrs();
  71   71  static int rfs4_fattr4_type();
  72   72  static int rfs4_fattr4_fh_expire_type();
  73   73  static int rfs4_fattr4_change();
  74   74  static int rfs4_fattr4_size();
  75   75  static int rfs4_fattr4_link_support();
  76   76  static int rfs4_fattr4_symlink_support();
  77   77  static int rfs4_fattr4_named_attr();
  78   78  static int rfs4_fattr4_fsid();
  79   79  static int rfs4_fattr4_unique_handles();
  80   80  static int rfs4_fattr4_lease_time();
  81   81  static int rfs4_fattr4_rdattr_error();
  82   82  static int rfs4_fattr4_acl();
  83   83  static int rfs4_fattr4_aclsupport();
  84   84  static int rfs4_fattr4_archive();
  85   85  static int rfs4_fattr4_cansettime();
  86   86  static int rfs4_fattr4_case_insensitive();
  87   87  static int rfs4_fattr4_case_preserving();
  88   88  static int rfs4_fattr4_chown_restricted();
  89   89  static int rfs4_fattr4_filehandle();
  90   90  static int rfs4_fattr4_fileid();
  91   91  static int rfs4_fattr4_files_avail();
  92   92  static int rfs4_fattr4_files_free();
  93   93  static int rfs4_fattr4_files_total();
  94   94  static int rfs4_fattr4_fs_locations();
  95   95  static int rfs4_fattr4_hidden();
  96   96  static int rfs4_fattr4_homogeneous();
  97   97  static int rfs4_fattr4_maxfilesize();
  98   98  static int rfs4_fattr4_maxlink();
  99   99  static int rfs4_fattr4_maxname();
 100  100  static int rfs4_fattr4_maxread();
 101  101  static int rfs4_fattr4_maxwrite();
 102  102  static int rfs4_fattr4_mimetype();
 103  103  static int rfs4_fattr4_mode();
 104  104  static int rfs4_fattr4_no_trunc();
 105  105  static int rfs4_fattr4_numlinks();
 106  106  static int rfs4_fattr4_owner();
 107  107  static int rfs4_fattr4_owner_group();
 108  108  static int rfs4_fattr4_quota_avail_hard();
 109  109  static int rfs4_fattr4_quota_avail_soft();
 110  110  static int rfs4_fattr4_quota_used();
 111  111  static int rfs4_fattr4_rawdev();
 112  112  static int rfs4_fattr4_space_avail();
 113  113  static int rfs4_fattr4_space_free();
 114  114  static int rfs4_fattr4_space_total();
 115  115  static int rfs4_fattr4_space_used();
 116  116  static int rfs4_fattr4_system();
 117  117  static int rfs4_fattr4_time_access();
 118  118  static int rfs4_fattr4_time_access_set();
 119  119  static int rfs4_fattr4_time_backup();
 120  120  static int rfs4_fattr4_time_create();
 121  121  static int rfs4_fattr4_time_delta();
 122  122  static int rfs4_fattr4_time_metadata();
 123  123  static int rfs4_fattr4_time_modify();
 124  124  static int rfs4_fattr4_time_modify_set();
 125  125  
 126  126  /*
 127  127   * Initialize the supported attributes
  
    | 
      ↓ open down ↓ | 
    127 lines elided | 
    
      ↑ open up ↑ | 
  
 128  128   */
 129  129  void
 130  130  rfs4_attr_init()
 131  131  {
 132  132          int i;
 133  133          struct nfs4_svgetit_arg sarg;
 134  134          struct compound_state cs;
 135  135          struct statvfs64 sb;
 136  136  
 137  137          rfs4_init_compound_state(&cs);
 138      -        cs.vp = ZONE_ROOTVP();
      138 +        /*
      139 +         * This is global state checking, called once. We might be in
      140 +         * non-global-zone context here (say a modload happens from a zone
      141 +         * process) so in this case, we want the global-zone root vnode.
      142 +         */
      143 +        cs.vp = rootvp;
 139  144          cs.fh.nfs_fh4_val = NULL;
 140  145          cs.cr = kcred;
 141  146  
 142  147          /*
 143  148           * Get all the supported attributes
 144  149           */
 145  150          sarg.op = NFS4ATTR_SUPPORTED;
 146  151          sarg.cs = &cs;
 147  152          sarg.vap->va_mask = AT_ALL;
 148  153          sarg.sbp = &sb;
 149  154          sarg.flag = 0;
 150  155          sarg.rdattr_error = NFS4_OK;
 151  156          sarg.rdattr_error_req = FALSE;
 152  157          sarg.is_referral = B_FALSE;
 153  158  
 154  159          rfs4_ntov_init();
 155  160  
 156  161          rfs4_supported_attrs = 0;
 157  162          for (i = 0; i < NFS4_MAXNUM_ATTRS; i++) {
 158  163  #ifdef RFS4_SUPPORT_MANDATTR_ONLY
 159  164                  if (rfs4_mandattr_only == TRUE && i > NFS4_LAST_MANDATTR)
 160  165                          continue;
 161  166  #endif
 162  167                  if ((*nfs4_ntov_map[i].sv_getit)(NFS4ATTR_SUPPORTED,
 163  168                      &sarg, NULL) == 0) {
 164  169                          rfs4_supported_attrs |= nfs4_ntov_map[i].fbit;
 165  170                  }
 166  171          }
 167  172  }
 168  173  
 169  174  /*
 170  175   * The following rfs4_fattr4_* functions convert between the fattr4
 171  176   * arguments/attributes and the system (e.g. vattr) values. The following
 172  177   * commands are currently in use:
 173  178   *
 174  179   * NFS4ATTR_SUPPORTED: checks if the attribute in question is supported:
 175  180   *      sarg.op = SUPPORTED - all supported attrs
 176  181   *      sarg.op = GETIT - only supported readable attrs
 177  182   *      sarg.op = SETIT - only supported writable attrs
 178  183   *
 179  184   * NFS4ATTR_GETIT: getattr type conversion - convert system values
 180  185   * (e.g. vattr struct) to fattr4 type values to be returned to the
 181  186   * user - usually in response to nfsv4 getattr request.
 182  187   *
 183  188   * NFS4ATTR_SETIT: convert fattr4 type values to system values to use by
 184  189   * setattr. Allows only read/write and write attributes,
 185  190   * even if not supported by the filesystem. Note that ufs only allows setattr
 186  191   * of owner/group, mode, size, atime/mtime.
 187  192   *
 188  193   * NFS4ATTR_VERIT: convert fattr4 type values to system values to use by
 189  194   * verify/nverify. Implemented to allow
 190  195   * almost everything that can be returned by getattr into known structs
 191  196   * (like vfsstat64 or vattr_t), that is, both read only and read/write attrs.
 192  197   * The function will return -1 if it found that the arguments don't match.
 193  198   * This applies to system-wide values that don't require a VOP_GETATTR
 194  199   * or other further checks to verify. It will return no error if they
 195  200   * either match or were retrieved successfully for later checking.
 196  201   *
 197  202   * NFS4ATTR_FREEIT: free up any space allocated by either of the above.
 198  203   * The sargp->op should be either NFS4ATTR_GETIT or NFS4ATTR_SETIT
 199  204   * to indicate which op was used to allocate the space.
 200  205   *
 201  206   * XXX Note: these functions are currently used by the server only. A
 202  207   * XXX different method of conversion is used on the client side.
 203  208   * XXX Eventually combining the two (possibly by adding NFS4ATTR_CLNT_GETIT
 204  209   * XXX and SETIT) may be a cleaner approach.
 205  210   */
 206  211  
 207  212  /*
 208  213   * Mandatory attributes
 209  214   */
 210  215  
 211  216  /* ARGSUSED */
 212  217  static int
 213  218  rfs4_fattr4_supported_attrs(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
 214  219      union nfs4_attr_u *na)
 215  220  {
 216  221          int     error = 0;
 217  222  
 218  223          switch (cmd) {
 219  224          case NFS4ATTR_SUPPORTED:
 220  225                  if (sarg->op == NFS4ATTR_SETIT)
 221  226                          error = EINVAL;
 222  227                  break;          /* this attr is supported */
 223  228          case NFS4ATTR_GETIT:
 224  229                  na->supported_attrs = rfs4_supported_attrs;
 225  230                  break;
 226  231          case NFS4ATTR_SETIT:
 227  232                  /*
 228  233                   * read-only attr
 229  234                   */
 230  235                  error = EINVAL;
 231  236                  break;
 232  237          case NFS4ATTR_VERIT:
 233  238                  /*
 234  239                   * Compare the input bitmap to the server's bitmap
 235  240                   */
 236  241                  if (na->supported_attrs != rfs4_supported_attrs) {
 237  242                          error = -1;     /* no match */
 238  243                  }
 239  244                  break;
 240  245          case NFS4ATTR_FREEIT:
 241  246                  break;
 242  247          }
 243  248          return (error);
 244  249  }
 245  250  
 246  251  /*
 247  252   * Translate vnode vtype to nfsv4_ftype.
 248  253   */
 249  254  static nfs_ftype4 vt_to_nf4[] = {
 250  255          0, NF4REG, NF4DIR, NF4BLK, NF4CHR, NF4LNK, NF4FIFO, 0, 0, NF4SOCK, 0
 251  256  };
 252  257  
 253  258  /* ARGSUSED */
 254  259  static int
 255  260  rfs4_fattr4_type(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
 256  261      union nfs4_attr_u *na)
 257  262  {
 258  263          int             error = 0;
 259  264  
 260  265          switch (cmd) {
 261  266          case NFS4ATTR_SUPPORTED:
 262  267                  if (sarg->op == NFS4ATTR_SETIT)
 263  268                          error = EINVAL;
 264  269                  break;          /* this attr is supported */
 265  270          case NFS4ATTR_GETIT:
 266  271                  if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_TYPE)) {
 267  272                          error = -1;     /* may be okay if rdattr_error */
 268  273                          break;
 269  274                  }
 270  275                  ASSERT(sarg->vap->va_mask & AT_TYPE);
 271  276  
 272  277                  /*
 273  278                   * if xattr flag not set, use v4_to_nf4 mapping;
 274  279                   * otherwise verify xattr flag is in sync with va_type
 275  280                   * and set xattr types.
 276  281                   */
 277  282                  if (! (sarg->xattr & (FH4_NAMEDATTR | FH4_ATTRDIR)))
 278  283                          na->type = vt_to_nf4[sarg->vap->va_type];
 279  284                  else {
 280  285                          /*
 281  286                           * FH4 flag was set.  Dir type maps to attrdir,
 282  287                           * and all other types map to namedattr.
 283  288                           */
 284  289                          if (sarg->vap->va_type == VDIR)
 285  290                                  na->type = NF4ATTRDIR;
 286  291                          else
 287  292                                  na->type = NF4NAMEDATTR;
 288  293                  }
 289  294                  break;
 290  295          case NFS4ATTR_SETIT:
 291  296                  /*
 292  297                   * read-only attr
 293  298                   */
 294  299                  error = EINVAL;
 295  300                  break;
 296  301          case NFS4ATTR_VERIT:
 297  302                  /*
 298  303                   * Compare the input type to the object type on server
 299  304                   */
 300  305                  ASSERT(sarg->vap->va_mask & AT_TYPE);
 301  306                  if (sarg->vap->va_type != nf4_to_vt[na->type])
 302  307                          error = -1;     /* no match */
 303  308                  break;
 304  309          case NFS4ATTR_FREEIT:
 305  310                  break;
 306  311          }
 307  312          return (error);
 308  313  }
 309  314  
 310  315  /* ARGSUSED */
 311  316  static int
 312  317  fattr4_get_fh_expire_type(struct exportinfo *exi, uint32_t *fh_expire_typep)
 313  318  {
 314  319  #ifdef  VOLATILE_FH_TEST
 315  320          int     ex_flags;
 316  321  
 317  322          if (exi == NULL)
 318  323                  return (ESTALE);
 319  324          ex_flags = exi->exi_export.ex_flags;
 320  325          if ((ex_flags & (EX_VOLFH | EX_VOLRNM | EX_VOLMIG | EX_NOEXPOPEN))
 321  326              == 0) {
 322  327                  *fh_expire_typep = FH4_PERSISTENT;
 323  328                  return (0);
 324  329          }
 325  330          *fh_expire_typep = 0;
 326  331  
 327  332          if (ex_flags & EX_NOEXPOPEN) {
 328  333                  /* file handles should not expire with open - not used */
 329  334                  *fh_expire_typep = FH4_NOEXPIRE_WITH_OPEN;
 330  335          }
 331  336          if (ex_flags & EX_VOLFH) {
 332  337                  /*
 333  338                   * file handles may expire any time - on share here.
 334  339                   * If volatile any, no need to check other flags.
 335  340                   */
 336  341                  *fh_expire_typep |= FH4_VOLATILE_ANY;
 337  342                  return (0);
 338  343          }
 339  344          if (ex_flags & EX_VOLRNM) {
 340  345                  /* file handles may expire on rename */
 341  346                  *fh_expire_typep |= FH4_VOL_RENAME;
 342  347          }
 343  348          if (ex_flags & EX_VOLMIG) {
 344  349                  /* file handles may expire on migration - not used */
 345  350                  *fh_expire_typep |= FH4_VOL_MIGRATION;
 346  351          }
 347  352  #else   /* not VOLATILE_FH_TEST */
 348  353          *fh_expire_typep = FH4_PERSISTENT;
 349  354  #endif  /* VOLATILE_FH_TEST */
 350  355  
 351  356          return (0);
 352  357  }
 353  358  
 354  359  /*
 355  360   * At this point the only volatile filehandles we allow (for test purposes
 356  361   * only) are either fh's that expire when the filesystem is shared (reshared),
 357  362   * fh's that expire on a rename and persistent ones.
 358  363   */
 359  364  /* ARGSUSED */
 360  365  static int
 361  366  rfs4_fattr4_fh_expire_type(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
 362  367      union nfs4_attr_u *na)
 363  368  {
 364  369          uint32_t fh_expire_type;
 365  370          int error = 0;
 366  371  
 367  372          switch (cmd) {
 368  373          case NFS4ATTR_SUPPORTED:
 369  374                  if (sarg->op == NFS4ATTR_SETIT)
 370  375                          error = EINVAL;
 371  376                  break;          /* this attr is supported */
 372  377          case NFS4ATTR_GETIT:
 373  378                  error = fattr4_get_fh_expire_type(sarg->cs->exi,
 374  379                      &na->fh_expire_type);
 375  380                  break;
 376  381          case NFS4ATTR_SETIT:
 377  382                  /*
 378  383                   * read-only attr
 379  384                   */
 380  385                  error = EINVAL;
 381  386                  break;
 382  387          case NFS4ATTR_VERIT:
 383  388                  error = fattr4_get_fh_expire_type(sarg->cs->exi,
 384  389                      &fh_expire_type);
 385  390                  if (!error && (na->fh_expire_type != fh_expire_type))
 386  391                          error = -1;     /* no match */
 387  392                  break;
 388  393          case NFS4ATTR_FREEIT:
 389  394                  break;
 390  395          }
 391  396          return (error);
 392  397  }
 393  398  
 394  399  static int
 395  400  fattr4_get_change(struct nfs4_svgetit_arg *sarg, fattr4_change *changep)
 396  401  {
 397  402          vattr_t vap2[1], *vap = sarg->vap;
 398  403          struct compound_state *cs = sarg->cs;
 399  404          vnode_t *vp = cs->vp;
 400  405          nfsstat4 status;
 401  406          timespec_t vis_change;
 402  407  
 403  408          if ((vap->va_mask & AT_CTIME) == 0) {
 404  409                  if (sarg->rdattr_error && (vp == NULL)) {
 405  410                          return (-1);    /* may be okay if rdattr_error */
 406  411                  }
 407  412                  ASSERT(vp != NULL);
 408  413                  vap = vap2;
 409  414                  vap->va_mask = AT_CTIME;
 410  415                  status = rfs4_vop_getattr(vp, vap, 0, cs->cr);
 411  416                  if (status != NFS4_OK)
 412  417                          return (geterrno4(status));
 413  418          }
 414  419          NFS4_SET_FATTR4_CHANGE(*changep, vap->va_ctime);
 415  420  
 416  421          if (nfs_visible_change(cs->exi, vp, &vis_change)) {
 417  422                  fattr4_change visch;
 418  423                  NFS4_SET_FATTR4_CHANGE(visch, vis_change);
 419  424                  if (visch > *changep)
 420  425                          *changep = visch;
 421  426          }
 422  427  
 423  428          return (0);
 424  429  }
 425  430  
 426  431  /* ARGSUSED */
 427  432  static int
 428  433  rfs4_fattr4_change(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
 429  434      union nfs4_attr_u *na)
 430  435  {
 431  436          int error = 0;
 432  437          fattr4_change change;
 433  438          uint_t mask;
 434  439          vattr_t *vap = sarg->vap;
 435  440  
 436  441          switch (cmd) {
 437  442          case NFS4ATTR_SUPPORTED:
 438  443                  if (sarg->op == NFS4ATTR_SETIT)
 439  444                          error = EINVAL;
 440  445                  break;          /* this attr is supported */
 441  446          case NFS4ATTR_GETIT:
 442  447                  error = fattr4_get_change(sarg, &na->change);
 443  448                  break;
 444  449          case NFS4ATTR_SETIT:
 445  450                  /*
 446  451                   * read-only attr
 447  452                   */
 448  453                  error = EINVAL;
 449  454                  break;
 450  455          case NFS4ATTR_VERIT:
 451  456                  mask = vap->va_mask;
 452  457                  vap->va_mask &= ~AT_CTIME;      /* force a VOP_GETATTR */
 453  458                  error = fattr4_get_change(sarg, &change);
 454  459                  vap->va_mask = mask;
 455  460                  if (!error && (na->change != change))
 456  461                          error = -1;
 457  462                  break;
 458  463          case NFS4ATTR_FREEIT:
 459  464                  break;
 460  465          }
 461  466          return (error);
 462  467  }
 463  468  
 464  469  /* ARGSUSED */
 465  470  static int
 466  471  rfs4_fattr4_size(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
 467  472      union nfs4_attr_u *na)
 468  473  {
 469  474          int     error = 0;
 470  475  
 471  476          switch (cmd) {
 472  477          case NFS4ATTR_SUPPORTED:
 473  478                  break;          /* this attr is supported */
 474  479          case NFS4ATTR_GETIT:
 475  480                  if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_SIZE)) {
 476  481                          error = -1;     /* may be okay if rdattr_error */
 477  482                          break;
 478  483                  }
 479  484                  ASSERT(sarg->vap->va_mask & AT_SIZE);
 480  485                  na->size = sarg->vap->va_size;
 481  486                  break;
 482  487          case NFS4ATTR_SETIT:
 483  488                  ASSERT(sarg->vap->va_mask & AT_SIZE);
 484  489                  sarg->vap->va_size = na->size;
 485  490                  break;
 486  491          case NFS4ATTR_VERIT:
 487  492                  ASSERT(sarg->vap->va_mask & AT_SIZE);
 488  493                  if (sarg->vap->va_size != na->size)
 489  494                          error = -1;     /* no match */
 490  495                  break;
 491  496          case NFS4ATTR_FREEIT:
 492  497                  break;
 493  498          }
 494  499          return (error);
 495  500  }
 496  501  
 497  502  /*
 498  503   * XXX - need VOP extension to ask file system (e.g. pcfs) if it supports
 499  504   * hard links.
 500  505   */
 501  506  /* ARGSUSED */
 502  507  static int
 503  508  rfs4_fattr4_link_support(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
 504  509      union nfs4_attr_u *na)
 505  510  {
 506  511          int error = 0;
 507  512  
 508  513          switch (cmd) {
 509  514          case NFS4ATTR_SUPPORTED:
 510  515                  if (sarg->op == NFS4ATTR_SETIT)
 511  516                          error = EINVAL;
 512  517                  break;          /* this attr is supported */
 513  518          case NFS4ATTR_GETIT:
 514  519                  na->link_support = TRUE;
 515  520                  break;
 516  521          case NFS4ATTR_SETIT:
 517  522                  /*
 518  523                   * read-only attr
 519  524                   */
 520  525                  error = EINVAL;
 521  526                  break;
 522  527          case NFS4ATTR_VERIT:
 523  528                  if (!na->link_support)
 524  529                          error = -1;     /* no match */
 525  530                  break;
 526  531          case NFS4ATTR_FREEIT:
 527  532                  break;
 528  533          }
 529  534          return (error);
 530  535  }
 531  536  
 532  537  /*
 533  538   * XXX - need VOP extension to ask file system (e.g. pcfs) if it supports
 534  539   * sym links.
 535  540   */
 536  541  /* ARGSUSED */
 537  542  static int
 538  543  rfs4_fattr4_symlink_support(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
 539  544      union nfs4_attr_u *na)
 540  545  {
 541  546          int error = 0;
 542  547  
 543  548          switch (cmd) {
 544  549          case NFS4ATTR_SUPPORTED:
 545  550                  if (sarg->op == NFS4ATTR_SETIT)
 546  551                          error = EINVAL;
 547  552                  break;          /* this attr is supported */
 548  553          case NFS4ATTR_GETIT:
 549  554                  na->symlink_support = TRUE;
 550  555                  break;
 551  556          case NFS4ATTR_SETIT:
 552  557                  /*
 553  558                   * read-only attr
 554  559                   */
 555  560                  error = EINVAL;
 556  561                  break;
 557  562          case NFS4ATTR_VERIT:
 558  563                  if (!na->symlink_support)
 559  564                          error = -1;     /* no match */
 560  565                  break;
 561  566          case NFS4ATTR_FREEIT:
 562  567                  break;
 563  568          }
 564  569          return (error);
 565  570  }
 566  571  
 567  572  /* ARGSUSED */
 568  573  static int
 569  574  rfs4_fattr4_named_attr(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
 570  575      union nfs4_attr_u *na)
 571  576  {
 572  577          int error = 0;
 573  578          ulong_t val;
 574  579  
 575  580          switch (cmd) {
 576  581          case NFS4ATTR_SUPPORTED:
 577  582                  if (sarg->op == NFS4ATTR_SETIT)
 578  583                          error = EINVAL;
 579  584                  break;          /* this attr is supported */
 580  585          case NFS4ATTR_GETIT:
 581  586                  if (sarg->rdattr_error && (sarg->cs->vp == NULL)) {
 582  587                          error = -1;     /* may be okay if rdattr_error */
 583  588                          break;
 584  589                  }
 585  590                  ASSERT(sarg->cs->vp != NULL);
 586  591  
 587  592                  /*
 588  593                   * Solaris xattr model requires that VFS_XATTR is set
 589  594                   * in file systems enabled for generic xattr.  If VFS_XATTR
 590  595                   * not set, no need to call pathconf for _PC_XATTR_EXISTS..
 591  596                   *
 592  597                   * However the VFS_XATTR flag doesn't indicate sysattr support
 593  598                   * so always check for sysattrs and then only do the
 594  599                   * _PC_XATTR_EXISTS pathconf if needed.
 595  600                   */
 596  601  
 597  602                  val = 0;
 598  603                  error = VOP_PATHCONF(sarg->cs->vp, _PC_SATTR_EXISTS,
 599  604                      &val, sarg->cs->cr, NULL);
 600  605                  if ((error || val == 0) &&
 601  606                      sarg->cs->vp->v_vfsp->vfs_flag & VFS_XATTR) {
 602  607                          error = VOP_PATHCONF(sarg->cs->vp,
 603  608                              _PC_XATTR_EXISTS, &val, sarg->cs->cr, NULL);
 604  609                          if (error)
 605  610                                  break;
 606  611                  }
 607  612                  na->named_attr = (val ? TRUE : FALSE);
 608  613                  break;
 609  614          case NFS4ATTR_SETIT:
 610  615                  /*
 611  616                   * read-only attr
 612  617                   */
 613  618                  error = EINVAL;
 614  619                  break;
 615  620          case NFS4ATTR_VERIT:
 616  621                  ASSERT(sarg->cs->vp != NULL);
 617  622                  if (sarg->cs->vp->v_vfsp->vfs_flag & VFS_XATTR) {
 618  623                          error = VOP_PATHCONF(sarg->cs->vp, _PC_SATTR_EXISTS,
 619  624                              &val, sarg->cs->cr, NULL);
 620  625                          if (error || val == 0)
 621  626                                  error = VOP_PATHCONF(sarg->cs->vp,
 622  627                                      _PC_XATTR_EXISTS, &val,
 623  628                                      sarg->cs->cr, NULL);
 624  629                          if (error)
 625  630                                  break;
 626  631                  } else
 627  632                          val = 0;
 628  633                  if (na->named_attr != (val ? TRUE : FALSE))
 629  634                          error = -1;     /* no match */
 630  635                  break;
 631  636          case NFS4ATTR_FREEIT:
 632  637                  break;
 633  638          }
 634  639          return (error);
 635  640  }
 636  641  
 637  642  /* ARGSUSED */
 638  643  static int
 639  644  rfs4_fattr4_fsid(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
 640  645      union nfs4_attr_u *na)
 641  646  {
 642  647          int error = 0;
 643  648          int *pmaj = (int *)&na->fsid.major;
 644  649  
 645  650          /*
 646  651           * fsid_t is 64bits so it fits completely in fattr4_fsid.major.
 647  652           * fattr4_fsid.minor is always set to 0 since it isn't needed (yet).
 648  653           */
 649  654          switch (cmd) {
 650  655          case NFS4ATTR_SUPPORTED:
 651  656                  if (sarg->op == NFS4ATTR_SETIT)
 652  657                          error = EINVAL;
 653  658                  break;          /* this attr is supported */
 654  659          case NFS4ATTR_GETIT:
 655  660                  if (sarg->is_referral) {
 656  661                          na->fsid.major = 1;
 657  662                          na->fsid.minor = 0;
 658  663                  } else if (sarg->cs->exi->exi_volatile_dev) {
 659  664                          pmaj[0] = sarg->cs->exi->exi_fsid.val[0];
 660  665                          pmaj[1] = sarg->cs->exi->exi_fsid.val[1];
 661  666                          na->fsid.minor = 0;
 662  667                  } else {
 663  668                          na->fsid.major = getmajor(sarg->vap->va_fsid);
 664  669                          na->fsid.minor = getminor(sarg->vap->va_fsid);
 665  670                  }
 666  671                  break;
 667  672          case NFS4ATTR_SETIT:
 668  673                  error = EINVAL;
 669  674                  break;
 670  675          case NFS4ATTR_VERIT:
 671  676                  if (sarg->is_referral) {
 672  677                          if (na->fsid.major != 1 ||
 673  678                              na->fsid.minor != 0)
 674  679                                  error = -1;
 675  680                  } else if (sarg->cs->exi->exi_volatile_dev) {
 676  681                          if (pmaj[0] != sarg->cs->exi->exi_fsid.val[0] ||
 677  682                              pmaj[1] != sarg->cs->exi->exi_fsid.val[1] ||
 678  683                              na->fsid.minor != 0)
 679  684                                  error = -1;
 680  685                  } else {
 681  686                          if (na->fsid.major != getmajor(sarg->vap->va_fsid) ||
 682  687                              na->fsid.minor != getminor(sarg->vap->va_fsid))
 683  688                                  error = -1;
 684  689                  }
 685  690                  break;
 686  691          case NFS4ATTR_FREEIT:
 687  692                  break;
 688  693          }
 689  694          return (error);
 690  695  }
 691  696  
 692  697  /* ARGSUSED */
 693  698  static int
 694  699  rfs4_fattr4_unique_handles(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
 695  700      union nfs4_attr_u *na)
 696  701  {
 697  702          /*
 698  703           * XXX
 699  704           * For now, we can't support this. Problem of /export, beinging
 700  705           * a file system, /export/a and /export/b shared separately,
 701  706           * and /export/a/l and /export/b/l are ahrd links of each other.
 702  707           */
 703  708          int error = 0;
 704  709  
 705  710          switch (cmd) {
 706  711          case NFS4ATTR_SUPPORTED:
 707  712                  if (sarg->op == NFS4ATTR_SETIT)
 708  713                          error = EINVAL;
 709  714                  break;          /* this attr is supported */
 710  715          case NFS4ATTR_GETIT:
 711  716                  na->unique_handles = FALSE;
 712  717                  break;
 713  718          case NFS4ATTR_SETIT:
 714  719                  /*
 715  720                   * read-only attr
 716  721                   */
 717  722                  error = EINVAL;
 718  723                  break;
 719  724          case NFS4ATTR_VERIT:
 720  725                  if (na->unique_handles)
 721  726                          error = -1;     /* no match */
 722  727                  break;
 723  728          case NFS4ATTR_FREEIT:
 724  729                  break;
 725  730          }
 726  731          return (error);
 727  732  }
 728  733  
 729  734  /* ARGSUSED */
 730  735  static int
 731  736  rfs4_fattr4_lease_time(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
 732  737      union nfs4_attr_u *na)
 733  738  {
 734  739          int error = 0;
 735  740  
 736  741          switch (cmd) {
 737  742          case NFS4ATTR_SUPPORTED:
 738  743                  if (sarg->op == NFS4ATTR_SETIT)
 739  744                          error = EINVAL;
 740  745                  break;          /* this attr is supported */
 741  746          case NFS4ATTR_GETIT:
 742  747                  na->lease_time = rfs4_lease_time;
 743  748                  break;
 744  749          case NFS4ATTR_SETIT:
 745  750                  /*
 746  751                   * read-only attr
 747  752                   */
 748  753                  error = EINVAL;
 749  754                  break;
 750  755          case NFS4ATTR_VERIT:
 751  756                  if (na->lease_time != rfs4_lease_time)
 752  757                          error = -1;     /* no match */
 753  758                  break;
 754  759          case NFS4ATTR_FREEIT:
 755  760                  break;
 756  761          }
 757  762          return (error);
 758  763  }
 759  764  
 760  765  /* ARGSUSED */
 761  766  static int
 762  767  rfs4_fattr4_rdattr_error(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
 763  768      union nfs4_attr_u *na)
 764  769  {
 765  770          int error = 0;
 766  771  
 767  772          switch (cmd) {
 768  773          case NFS4ATTR_SUPPORTED:
 769  774                  if ((sarg->op == NFS4ATTR_SETIT) ||
 770  775                      (sarg->op == NFS4ATTR_VERIT))
 771  776                          error = EINVAL;
 772  777                  break;          /* this attr is supported */
 773  778          case NFS4ATTR_GETIT:
 774  779                  ASSERT(sarg->rdattr_error_req);
 775  780                  na->rdattr_error = sarg->rdattr_error;
 776  781                  break;
 777  782          case NFS4ATTR_SETIT:
 778  783          case NFS4ATTR_VERIT:
 779  784                  /*
 780  785                   * read-only attr
 781  786                   */
 782  787                  error = EINVAL;
 783  788                  break;
 784  789          case NFS4ATTR_FREEIT:
 785  790                  break;
 786  791          }
 787  792          return (error);
 788  793  }
 789  794  
 790  795  /*
 791  796   * Server side compare of a filehandle from the wire to a native
 792  797   * server filehandle.
 793  798   */
 794  799  static int
 795  800  rfs4fhcmp(nfs_fh4 *wirefh, nfs_fh4 *srvfh)
 796  801  {
 797  802          nfs_fh4_fmt_t fh;
 798  803  
 799  804          ASSERT(IS_P2ALIGNED(wirefh->nfs_fh4_val, sizeof (uint32_t)));
 800  805  
 801  806          bzero(&fh, sizeof (nfs_fh4_fmt_t));
 802  807          if (!xdr_inline_decode_nfs_fh4((uint32_t *)wirefh->nfs_fh4_val, &fh,
 803  808              wirefh->nfs_fh4_len))
 804  809                  return (1);
 805  810  
 806  811          return (bcmp(srvfh->nfs_fh4_val, &fh, srvfh->nfs_fh4_len));
 807  812  }
 808  813  
 809  814  /* ARGSUSED */
 810  815  static int
 811  816  rfs4_fattr4_filehandle(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
 812  817      union nfs4_attr_u *na)
 813  818  {
 814  819          nfs_fh4 *fh;
 815  820  
 816  821          switch (cmd) {
 817  822          case NFS4ATTR_SUPPORTED:
 818  823                  if (sarg->op == NFS4ATTR_SETIT)
 819  824                          return (EINVAL);
 820  825                  return (0);     /* this attr is supported */
 821  826          case NFS4ATTR_GETIT:
 822  827                  /*
 823  828                   * If sarg->cs->fh is all zeros then should makefh a new
 824  829                   * one, otherwise, copy that one over.
 825  830                   */
 826  831                  fh = &sarg->cs->fh;
 827  832                  if (sarg->cs->fh.nfs_fh4_len == 0) {
 828  833                          if (sarg->rdattr_error && (sarg->cs->vp == NULL))
 829  834                                  return (-1);    /* okay if rdattr_error */
 830  835                          ASSERT(sarg->cs->vp != NULL);
 831  836                          na->filehandle.nfs_fh4_val =
 832  837                              kmem_alloc(NFS_FH4_LEN, KM_SLEEP);
 833  838                          return (makefh4(&na->filehandle, sarg->cs->vp,
 834  839                              sarg->cs->exi));
 835  840                  }
 836  841                  na->filehandle.nfs_fh4_val =
 837  842                      kmem_alloc(fh->nfs_fh4_len, KM_SLEEP);
 838  843                  nfs_fh4_copy(fh, &na->filehandle);
 839  844                  return (0);
 840  845          case NFS4ATTR_SETIT:
 841  846                  /*
 842  847                   * read-only attr
 843  848                   */
 844  849                  return (EINVAL);
 845  850          case NFS4ATTR_VERIT:
 846  851                  /*
 847  852                   * A verify of a filehandle will have the client sending
 848  853                   * the raw format which needs to be compared to the
 849  854                   * native format.
 850  855                   */
 851  856                  if (rfs4fhcmp(&na->filehandle, &sarg->cs->fh) == 1)
 852  857                          return (-1);    /* no match */
 853  858                  return (0);
 854  859          case NFS4ATTR_FREEIT:
 855  860                  if (sarg->op != NFS4ATTR_GETIT)
 856  861                          return (0);
 857  862                  if (na->filehandle.nfs_fh4_val == NULL)
 858  863                          return (0);
 859  864                  kmem_free(na->filehandle.nfs_fh4_val,
 860  865                      na->filehandle.nfs_fh4_len);
 861  866                  na->filehandle.nfs_fh4_val = NULL;
 862  867                  na->filehandle.nfs_fh4_len = 0;
 863  868                  return (0);
 864  869          }
 865  870          return (0);
 866  871  }
 867  872  
 868  873  /*
 869  874   * Recommended attributes
 870  875   */
 871  876  
 872  877  /* ARGSUSED */
 873  878  static int
 874  879  rfs4_fattr4_acl(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
 875  880      union nfs4_attr_u *na)
 876  881  {
 877  882          int error = 0;
 878  883          vsecattr_t vs_native, vs_ace4;
 879  884          ulong_t whichacl;
 880  885          nfsstat4 status;
 881  886          vattr_t va, *vap = sarg->vap;
 882  887          vnode_t *vp = sarg->cs->vp;
 883  888  
 884  889          if (RFS4_MANDATTR_ONLY)
 885  890                  return (ENOTSUP);
 886  891  
 887  892          switch (cmd) {
 888  893          case NFS4ATTR_SUPPORTED:
 889  894                  break;
 890  895  
 891  896          case NFS4ATTR_VERIT:
 892  897          case NFS4ATTR_GETIT:
 893  898                  if (sarg->rdattr_error && (vp == NULL)) {
 894  899                          return (-1);
 895  900                  }
 896  901                  ASSERT(vp != NULL);
 897  902                  bzero(&vs_native, sizeof (vs_native));
 898  903  
 899  904                  /* see which ACLs fs supports */
 900  905                  error = VOP_PATHCONF(vp, _PC_ACL_ENABLED, &whichacl,
 901  906                      sarg->cs->cr, NULL);
 902  907                  if (error != 0) {
 903  908                          /*
 904  909                           * If we got an error, then the filesystem
 905  910                           * likely does not understand the _PC_ACL_ENABLED
 906  911                           * pathconf.  In this case, we fall back to trying
 907  912                           * POSIX-draft (aka UFS-style) ACLs, since that's
 908  913                           * the behavior used by earlier version of NFS.
 909  914                           */
 910  915                          error = 0;
 911  916                          whichacl = _ACL_ACLENT_ENABLED;
 912  917                  }
 913  918  
 914  919                  if (!(whichacl & (_ACL_ACE_ENABLED | _ACL_ACLENT_ENABLED))) {
 915  920                          /*
 916  921                           * If the file system supports neither ACE nor
 917  922                           * ACLENT ACLs we will fall back to UFS-style ACLs
 918  923                           * like we did above if there was an error upon
 919  924                           * calling VOP_PATHCONF.
 920  925                           *
 921  926                           * ACE and ACLENT type ACLs are the only interfaces
 922  927                           * supported thus far.  If any other bits are set on
 923  928                           * 'whichacl' upon return from VOP_PATHCONF, we will
 924  929                           * ignore them.
 925  930                           */
 926  931                          whichacl = _ACL_ACLENT_ENABLED;
 927  932                  }
 928  933  
 929  934                  if (whichacl & _ACL_ACE_ENABLED)
 930  935                          vs_native.vsa_mask = VSA_ACE | VSA_ACECNT;
 931  936                  else if (whichacl & _ACL_ACLENT_ENABLED)
 932  937                          vs_native.vsa_mask = VSA_ACL | VSA_ACLCNT |
 933  938                              VSA_DFACL | VSA_DFACLCNT;
 934  939  
 935  940                  if (error != 0)
 936  941                          break;
 937  942  
 938  943                  /* get the ACL, and translate it into nfsace4 style */
 939  944                  error = VOP_GETSECATTR(vp, &vs_native,
 940  945                      0, sarg->cs->cr, NULL);
 941  946                  if (error != 0)
 942  947                          break;
 943  948                  if (whichacl & _ACL_ACE_ENABLED) {
 944  949                          error = vs_acet_to_ace4(&vs_native, &vs_ace4, TRUE);
 945  950                          vs_acet_destroy(&vs_native);
 946  951                  } else {
 947  952                          error = vs_aent_to_ace4(&vs_native, &vs_ace4,
 948  953                              vp->v_type == VDIR, TRUE);
 949  954                          vs_aent_destroy(&vs_native);
 950  955                  }
 951  956                  if (error != 0)
 952  957                          break;
 953  958  
 954  959                  if (cmd == NFS4ATTR_GETIT) {
 955  960                          na->acl.fattr4_acl_len = vs_ace4.vsa_aclcnt;
 956  961                          /* see case NFS4ATTR_FREEIT for this being freed */
 957  962                          na->acl.fattr4_acl_val = vs_ace4.vsa_aclentp;
 958  963                  } else {
 959  964                          if (na->acl.fattr4_acl_len != vs_ace4.vsa_aclcnt)
 960  965                                  error = -1; /* no match */
 961  966                          else if (ln_ace4_cmp(na->acl.fattr4_acl_val,
 962  967                              vs_ace4.vsa_aclentp,
 963  968                              vs_ace4.vsa_aclcnt) != 0)
 964  969                                  error = -1; /* no match */
 965  970                  }
 966  971  
 967  972                  break;
 968  973  
 969  974          case NFS4ATTR_SETIT:
 970  975                  if (sarg->rdattr_error && (vp == NULL)) {
 971  976                          return (-1);
 972  977                  }
 973  978                  ASSERT(vp != NULL);
 974  979  
 975  980                  /* prepare vs_ace4 from fattr4 data */
 976  981                  bzero(&vs_ace4, sizeof (vs_ace4));
 977  982                  vs_ace4.vsa_mask = VSA_ACE | VSA_ACECNT;
 978  983                  vs_ace4.vsa_aclcnt = na->acl.fattr4_acl_len;
 979  984                  vs_ace4.vsa_aclentp = na->acl.fattr4_acl_val;
 980  985                  vs_ace4.vsa_aclentsz = vs_ace4.vsa_aclcnt * sizeof (ace_t);
 981  986                  /* make sure we have correct owner/group */
 982  987                  if ((vap->va_mask & (AT_UID | AT_GID)) !=
 983  988                      (AT_UID | AT_GID)) {
 984  989                          vap = &va;
 985  990                          vap->va_mask = AT_UID | AT_GID;
 986  991                          status = rfs4_vop_getattr(vp,
 987  992                              vap, 0, sarg->cs->cr);
 988  993                          if (status != NFS4_OK)
 989  994                                  return (geterrno4(status));
 990  995                  }
 991  996  
 992  997                  /* see which ACLs the fs supports */
 993  998                  error = VOP_PATHCONF(vp, _PC_ACL_ENABLED, &whichacl,
 994  999                      sarg->cs->cr, NULL);
 995 1000                  if (error != 0) {
 996 1001                          /*
 997 1002                           * If we got an error, then the filesystem
 998 1003                           * likely does not understand the _PC_ACL_ENABLED
 999 1004                           * pathconf.  In this case, we fall back to trying
1000 1005                           * POSIX-draft (aka UFS-style) ACLs, since that's
1001 1006                           * the behavior used by earlier version of NFS.
1002 1007                           */
1003 1008                          error = 0;
1004 1009                          whichacl = _ACL_ACLENT_ENABLED;
1005 1010                  }
1006 1011  
1007 1012                  if (!(whichacl & (_ACL_ACLENT_ENABLED | _ACL_ACE_ENABLED))) {
1008 1013                          /*
1009 1014                           * If the file system supports neither ACE nor
1010 1015                           * ACLENT ACLs we will fall back to UFS-style ACLs
1011 1016                           * like we did above if there was an error upon
1012 1017                           * calling VOP_PATHCONF.
1013 1018                           *
1014 1019                           * ACE and ACLENT type ACLs are the only interfaces
1015 1020                           * supported thus far.  If any other bits are set on
1016 1021                           * 'whichacl' upon return from VOP_PATHCONF, we will
1017 1022                           * ignore them.
1018 1023                           */
1019 1024                          whichacl = _ACL_ACLENT_ENABLED;
1020 1025                  }
1021 1026  
1022 1027                  if (whichacl & _ACL_ACE_ENABLED) {
1023 1028                          error = vs_ace4_to_acet(&vs_ace4, &vs_native,
1024 1029                              vap->va_uid, vap->va_gid, TRUE);
1025 1030                          if (error != 0)
1026 1031                                  break;
1027 1032                          (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL);
1028 1033                          error = VOP_SETSECATTR(vp, &vs_native,
1029 1034                              0, sarg->cs->cr, NULL);
1030 1035                          VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
1031 1036                          vs_acet_destroy(&vs_native);
1032 1037                  } else if (whichacl & _ACL_ACLENT_ENABLED) {
1033 1038                          error = vs_ace4_to_aent(&vs_ace4, &vs_native,
1034 1039                              vap->va_uid, vap->va_gid, vp->v_type == VDIR, TRUE);
1035 1040                          if (error != 0)
1036 1041                                  break;
1037 1042                          (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL);
1038 1043                          error = VOP_SETSECATTR(vp, &vs_native,
1039 1044                              0, sarg->cs->cr, NULL);
1040 1045                          VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
1041 1046                          vs_aent_destroy(&vs_native);
1042 1047                  }
1043 1048                  break;
1044 1049  
1045 1050          case NFS4ATTR_FREEIT:
1046 1051                  if (sarg->op == NFS4ATTR_GETIT) {
1047 1052                          vs_ace4.vsa_mask = VSA_ACE | VSA_ACECNT;
1048 1053                          vs_ace4.vsa_aclcnt = na->acl.fattr4_acl_len;
1049 1054                          vs_ace4.vsa_aclentp = na->acl.fattr4_acl_val;
1050 1055                          vs_ace4_destroy(&vs_ace4);
1051 1056                  }
1052 1057                  break;
1053 1058          }
1054 1059  
1055 1060          return (error);
1056 1061  }
1057 1062  
1058 1063  /* ARGSUSED */
1059 1064  static int
1060 1065  rfs4_fattr4_aclsupport(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1061 1066      union nfs4_attr_u *na)
1062 1067  {
1063 1068          int error = 0;
1064 1069  
1065 1070          if (RFS4_MANDATTR_ONLY)
1066 1071                  return (ENOTSUP);
1067 1072  
1068 1073          switch (cmd) {
1069 1074          case NFS4ATTR_SUPPORTED:
1070 1075                  if (sarg->op == NFS4ATTR_SETIT)
1071 1076                          error = EINVAL;
1072 1077                  break;  /* supported */
1073 1078          case NFS4ATTR_GETIT:
1074 1079                  na->aclsupport = ACL4_SUPPORT_ALLOW_ACL |
1075 1080                      ACL4_SUPPORT_DENY_ACL;
1076 1081                  break;
1077 1082          case NFS4ATTR_SETIT:
1078 1083                  error = EINVAL;
1079 1084                  break;
1080 1085          case NFS4ATTR_VERIT:
1081 1086                  if (na->aclsupport != (ACL4_SUPPORT_ALLOW_ACL |
1082 1087                      ACL4_SUPPORT_DENY_ACL))
1083 1088                          error = -1;     /* no match */
1084 1089                  break;
1085 1090          }
1086 1091  
1087 1092          return (error);
1088 1093  }
1089 1094  
1090 1095  /* ARGSUSED */
1091 1096  static int
1092 1097  rfs4_fattr4_archive(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1093 1098      union nfs4_attr_u *na)
1094 1099  {
1095 1100          return (ENOTSUP);
1096 1101  }
1097 1102  
1098 1103  /* ARGSUSED */
1099 1104  static int
1100 1105  rfs4_fattr4_cansettime(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1101 1106      union nfs4_attr_u *na)
1102 1107  {
1103 1108          int error = 0;
1104 1109  
1105 1110          if (RFS4_MANDATTR_ONLY)
1106 1111                  return (ENOTSUP);
1107 1112  
1108 1113          switch (cmd) {
1109 1114          case NFS4ATTR_SUPPORTED:
1110 1115                  if (sarg->op == NFS4ATTR_SETIT)
1111 1116                          error = EINVAL;
1112 1117                  break;          /* this attr is supported */
1113 1118          case NFS4ATTR_GETIT:
1114 1119                  na->cansettime = TRUE;
1115 1120                  break;
1116 1121          case NFS4ATTR_SETIT:
1117 1122                  /*
1118 1123                   * read-only attr
1119 1124                   */
1120 1125                  error = EINVAL;
1121 1126                  break;
1122 1127          case NFS4ATTR_VERIT:
1123 1128                  if (!na->cansettime)
1124 1129                          error = -1;     /* no match */
1125 1130                  break;
1126 1131          case NFS4ATTR_FREEIT:
1127 1132                  break;
1128 1133          }
1129 1134          return (error);
1130 1135  }
1131 1136  
1132 1137  /*
1133 1138   * XXX - need VOP extension to ask file system (e.g. pcfs) if it supports
1134 1139   * case insensitive.
1135 1140   */
1136 1141  /* ARGSUSED */
1137 1142  static int
1138 1143  rfs4_fattr4_case_insensitive(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1139 1144      union nfs4_attr_u *na)
1140 1145  {
1141 1146          int error = 0;
1142 1147  
1143 1148          if (RFS4_MANDATTR_ONLY)
1144 1149                  return (ENOTSUP);
1145 1150  
1146 1151          switch (cmd) {
1147 1152          case NFS4ATTR_SUPPORTED:
1148 1153                  if (sarg->op == NFS4ATTR_SETIT)
1149 1154                          error = EINVAL;
1150 1155                  break;          /* this attr is supported */
1151 1156          case NFS4ATTR_GETIT:
1152 1157                  na->case_insensitive = FALSE;
1153 1158                  break;
1154 1159          case NFS4ATTR_SETIT:
1155 1160                  /*
1156 1161                   * read-only attr
1157 1162                   */
1158 1163                  error = EINVAL;
1159 1164                  break;
1160 1165          case NFS4ATTR_VERIT:
1161 1166                  if (!na->case_insensitive)
1162 1167                          error = -1;     /* no match */
1163 1168                  break;
1164 1169          case NFS4ATTR_FREEIT:
1165 1170                  break;
1166 1171          }
1167 1172          return (error);
1168 1173  }
1169 1174  
1170 1175  /* ARGSUSED */
1171 1176  static int
1172 1177  rfs4_fattr4_case_preserving(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1173 1178      union nfs4_attr_u *na)
1174 1179  {
1175 1180          int error = 0;
1176 1181  
1177 1182          if (RFS4_MANDATTR_ONLY)
1178 1183                  return (ENOTSUP);
1179 1184  
1180 1185          switch (cmd) {
1181 1186          case NFS4ATTR_SUPPORTED:
1182 1187                  if (sarg->op == NFS4ATTR_SETIT)
1183 1188                          error = EINVAL;
1184 1189                  break;          /* this attr is supported */
1185 1190          case NFS4ATTR_GETIT:
1186 1191                  na->case_preserving = TRUE;
1187 1192                  break;
1188 1193          case NFS4ATTR_SETIT:
1189 1194                  /*
1190 1195                   * read-only attr
1191 1196                   */
1192 1197                  error = EINVAL;
1193 1198                  break;
1194 1199          case NFS4ATTR_VERIT:
1195 1200                  if (!na->case_preserving)
1196 1201                          error = -1;     /* no match */
1197 1202                  break;
1198 1203          case NFS4ATTR_FREEIT:
1199 1204                  break;
1200 1205          }
1201 1206          return (error);
1202 1207  }
1203 1208  
1204 1209  /* fattr4_chown_restricted should reall be fattr4_chown_allowed */
1205 1210  /* ARGSUSED */
1206 1211  static int
1207 1212  rfs4_fattr4_chown_restricted(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1208 1213      union nfs4_attr_u *na)
1209 1214  {
1210 1215          int error = 0;
1211 1216          ulong_t val;
1212 1217  
1213 1218          if (RFS4_MANDATTR_ONLY)
1214 1219                  return (ENOTSUP);
1215 1220  
1216 1221          switch (cmd) {
1217 1222          case NFS4ATTR_SUPPORTED:
1218 1223                  if (sarg->op == NFS4ATTR_SETIT)
1219 1224                          error = EINVAL;
1220 1225                  break;          /* this attr is supported */
1221 1226          case NFS4ATTR_GETIT:
1222 1227                  if (sarg->rdattr_error && (sarg->cs->vp == NULL)) {
1223 1228                          error = -1;     /* may be okay if rdattr_error */
1224 1229                          break;
1225 1230                  }
1226 1231                  ASSERT(sarg->cs->vp != NULL);
1227 1232                  error = VOP_PATHCONF(sarg->cs->vp,
1228 1233                      _PC_CHOWN_RESTRICTED, &val, sarg->cs->cr, NULL);
1229 1234                  if (error)
1230 1235                          break;
1231 1236  
1232 1237                  na->chown_restricted = (val == 1);
1233 1238                  break;
1234 1239          case NFS4ATTR_SETIT:
1235 1240                  /*
1236 1241                   * read-only attr
1237 1242                   */
1238 1243                  error = EINVAL;
1239 1244                  break;
1240 1245          case NFS4ATTR_VERIT:
1241 1246                  ASSERT(sarg->cs->vp != NULL);
1242 1247                  error = VOP_PATHCONF(sarg->cs->vp,
1243 1248                      _PC_CHOWN_RESTRICTED, &val, sarg->cs->cr, NULL);
1244 1249                  if (error)
1245 1250                          break;
1246 1251                  if (na->chown_restricted != (val == 1))
1247 1252                          error = -1;     /* no match */
1248 1253                  break;
1249 1254          case NFS4ATTR_FREEIT:
1250 1255                  break;
1251 1256          }
1252 1257          return (error);
1253 1258  }
1254 1259  
1255 1260  /* ARGSUSED */
1256 1261  static int
1257 1262  rfs4_fattr4_fileid(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1258 1263      union nfs4_attr_u *na)
1259 1264  {
1260 1265          int     error = 0;
1261 1266  
1262 1267          if (RFS4_MANDATTR_ONLY)
1263 1268                  return (ENOTSUP);
1264 1269  
1265 1270          switch (cmd) {
1266 1271          case NFS4ATTR_SUPPORTED:
1267 1272                  if (sarg->op == NFS4ATTR_SETIT)
1268 1273                          error = EINVAL;
1269 1274                  break;          /* this attr is supported */
1270 1275          case NFS4ATTR_GETIT:
1271 1276                  if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_NODEID)) {
1272 1277                          error = -1;     /* may be okay if rdattr_error */
1273 1278                          break;
1274 1279                  }
1275 1280                  ASSERT(sarg->vap->va_mask & AT_NODEID);
1276 1281                  na->fileid = sarg->vap->va_nodeid;
1277 1282                  break;
1278 1283          case NFS4ATTR_SETIT:
1279 1284                  /*
1280 1285                   * read-only attr
1281 1286                   */
1282 1287                  error = EINVAL;
1283 1288                  break;
1284 1289          case NFS4ATTR_VERIT:
1285 1290                  ASSERT(sarg->vap->va_mask & AT_NODEID);
1286 1291                  if (sarg->vap->va_nodeid != na->fileid)
1287 1292                          error = -1;     /* no match */
1288 1293                  break;
1289 1294          case NFS4ATTR_FREEIT:
1290 1295                  break;
1291 1296          }
1292 1297          return (error);
1293 1298  }
1294 1299  
1295 1300  /* ARGSUSED */
  
    | 
      ↓ open down ↓ | 
    1147 lines elided | 
    
      ↑ open up ↑ | 
  
1296 1301  static int
1297 1302  rfs4_get_mntdfileid(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg)
1298 1303  {
1299 1304          int error = 0;
1300 1305          vattr_t *vap, va;
1301 1306          vnode_t *stubvp = NULL, *vp;
1302 1307  
1303 1308          vp = sarg->cs->vp;
1304 1309          sarg->mntdfid_set = FALSE;
1305 1310  
1306      -        /* VROOT object, must untraverse */
1307      -        if (vp->v_flag & VROOT) {
     1311 +        /*
     1312 +         * VROOT object or zone's root, must untraverse.
     1313 +         *
     1314 +         * NOTE: Not doing reality checks on curzone vs. compound
     1315 +         * state vnode because it will mismatch once at initialization
     1316 +         * if a non-global-zone triggers the module load, BUT in that case
     1317 +         * the vp is literally "/" which has VROOT set.
     1318 +         */
     1319 +        if ((vp->v_flag & VROOT) || VN_IS_CURZONEROOT(vp)) {
1308 1320  
1309 1321                  /* extra hold for vp since untraverse might rele */
1310 1322                  VN_HOLD(vp);
1311 1323                  stubvp = untraverse(vp);
1312 1324  
1313 1325                  /*
1314      -                 * If vp/stubvp are same, we must be at system
     1326 +                 * If vp/stubvp are same, we must be at system-or-zone
1315 1327                   * root because untraverse returned same vp
1316 1328                   * for a VROOT object.  sarg->vap was setup
1317 1329                   * before we got here, so there's no need to do
1318 1330                   * another getattr -- just use the one in sarg.
1319 1331                   */
1320 1332                  if (VN_CMP(vp, stubvp)) {
1321      -                        ASSERT(VN_CMP(vp, ZONE_ROOTVP()));
     1333 +                        ASSERT(VN_IS_CURZONEROOT(vp));
1322 1334                          vap = sarg->vap;
1323 1335                  } else {
1324 1336                          va.va_mask = AT_NODEID;
1325 1337                          vap = &va;
1326 1338                          error = rfs4_vop_getattr(stubvp, vap, 0, sarg->cs->cr);
1327 1339                  }
1328 1340  
1329 1341                  /*
1330 1342                   * Done with stub, time to rele.  If vp and stubvp
1331 1343                   * were the same, then we need to rele either vp or
1332 1344                   * stubvp.  If they weren't the same, then untraverse()
1333 1345                   * already took case of the extra hold on vp, and only
1334 1346                   * the stub needs to be rele'd.  Both cases are handled
1335 1347                   * by unconditionally rele'ing the stub.
1336 1348                   */
1337 1349                  VN_RELE(stubvp);
1338 1350          } else
1339 1351                  vap = sarg->vap;
1340 1352  
1341 1353          /*
1342 1354           * At this point, vap should contain "correct" AT_NODEID --
1343 1355           * (for V_ROOT case, nodeid of stub, for non-VROOT case,
1344 1356           * nodeid of vp).  If error or AT_NODEID not available, then
1345 1357           * make the obligatory (yet mysterious) rdattr_error
1346 1358           * check that is so common in the attr code.
1347 1359           */
1348 1360          if (!error && (vap->va_mask & AT_NODEID)) {
1349 1361                  sarg->mounted_on_fileid = vap->va_nodeid;
1350 1362                  sarg->mntdfid_set = TRUE;
1351 1363          } else if (sarg->rdattr_error)
1352 1364                  error = -1;
1353 1365  
1354 1366          /*
1355 1367           * error describes these cases:
1356 1368           *      0 : success
1357 1369           *      -1: failure due to previous attr processing error (rddir only).
1358 1370           *      * : new attr failure  (if rddir, caller will set rdattr_error)
1359 1371           */
1360 1372          return (error);
1361 1373  }
1362 1374  
1363 1375  /* ARGSUSED */
1364 1376  static int
1365 1377  rfs4_fattr4_mounted_on_fileid(nfs4_attr_cmd_t cmd,
1366 1378      struct nfs4_svgetit_arg *sarg, union nfs4_attr_u *na)
1367 1379  {
1368 1380          int     error = 0;
1369 1381  
  
    | 
      ↓ open down ↓ | 
    38 lines elided | 
    
      ↑ open up ↑ | 
  
1370 1382          if (RFS4_MANDATTR_ONLY)
1371 1383                  return (ENOTSUP);
1372 1384  
1373 1385          switch (cmd) {
1374 1386          case NFS4ATTR_SUPPORTED:
1375 1387                  if (sarg->op == NFS4ATTR_SETIT)
1376 1388                          error = EINVAL;
1377 1389                  break;          /* this attr is supported */
1378 1390          case NFS4ATTR_GETIT:
1379 1391          case NFS4ATTR_VERIT:
1380      -                if (! sarg->mntdfid_set)
     1392 +                if (!sarg->mntdfid_set)
1381 1393                          error = rfs4_get_mntdfileid(cmd, sarg);
1382 1394  
1383      -                if (! error && sarg->mntdfid_set) {
     1395 +                if (!error && sarg->mntdfid_set) {
1384 1396                          if (cmd == NFS4ATTR_GETIT)
1385 1397                                  na->mounted_on_fileid = sarg->mounted_on_fileid;
1386 1398                          else
1387 1399                                  if (na->mounted_on_fileid !=
1388 1400                                      sarg->mounted_on_fileid)
1389 1401                                          error = -1;
1390 1402                  }
1391 1403                  break;
1392 1404          case NFS4ATTR_SETIT:
1393 1405                  /* read-only attr */
1394 1406                  error = EINVAL;
1395 1407                  break;
1396 1408          case NFS4ATTR_FREEIT:
1397 1409                  break;
1398 1410          }
1399 1411          return (error);
1400 1412  }
1401 1413  
1402 1414  /* ARGSUSED */
1403 1415  static int
1404 1416  rfs4_fattr4_files_avail(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1405 1417      union nfs4_attr_u *na)
1406 1418  {
1407 1419          int     error = 0;
1408 1420  
1409 1421          if (RFS4_MANDATTR_ONLY)
1410 1422                  return (ENOTSUP);
1411 1423  
1412 1424          switch (cmd) {
1413 1425          case NFS4ATTR_SUPPORTED:
1414 1426                  if (sarg->op == NFS4ATTR_SETIT)
1415 1427                          error = EINVAL;
1416 1428                  break;          /* this attr is supported */
1417 1429          case NFS4ATTR_GETIT:
1418 1430                  if (sarg->rdattr_error && (sarg->sbp == NULL)) {
1419 1431                          error = -1;     /* may be okay if rdattr_error */
1420 1432                          break;
1421 1433                  }
1422 1434                  ASSERT(sarg->sbp != NULL);
1423 1435                  na->files_avail = sarg->sbp->f_favail;
1424 1436                  break;
1425 1437          case NFS4ATTR_SETIT:
1426 1438                  /*
1427 1439                   * read-only attr
1428 1440                   */
1429 1441                  error = EINVAL;
1430 1442                  break;
1431 1443          case NFS4ATTR_VERIT:
1432 1444                  ASSERT(sarg->sbp != NULL);
1433 1445                  if (sarg->sbp->f_favail != na->files_avail)
1434 1446                          error = -1;     /* no match */
1435 1447                  break;
1436 1448          case NFS4ATTR_FREEIT:
1437 1449                  break;
1438 1450          }
1439 1451          return (error);
1440 1452  }
1441 1453  
1442 1454  /* ARGSUSED */
1443 1455  static int
1444 1456  rfs4_fattr4_files_free(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1445 1457      union nfs4_attr_u *na)
1446 1458  {
1447 1459          int     error = 0;
1448 1460  
1449 1461          if (RFS4_MANDATTR_ONLY)
1450 1462                  return (ENOTSUP);
1451 1463  
1452 1464          switch (cmd) {
1453 1465          case NFS4ATTR_SUPPORTED:
1454 1466                  if (sarg->op == NFS4ATTR_SETIT)
1455 1467                          error = EINVAL;
1456 1468                  break;          /* this attr is supported */
1457 1469          case NFS4ATTR_GETIT:
1458 1470                  if (sarg->rdattr_error && (sarg->sbp == NULL)) {
1459 1471                          error = -1;     /* may be okay if rdattr_error */
1460 1472                          break;
1461 1473                  }
1462 1474                  ASSERT(sarg->sbp != NULL);
1463 1475                  na->files_free = sarg->sbp->f_ffree;
1464 1476                  break;
1465 1477          case NFS4ATTR_SETIT:
1466 1478                  /*
1467 1479                   * read-only attr
1468 1480                   */
1469 1481                  error = EINVAL;
1470 1482                  break;
1471 1483          case NFS4ATTR_VERIT:
1472 1484                  ASSERT(sarg->sbp != NULL);
1473 1485                  if (sarg->sbp->f_ffree != na->files_free)
1474 1486                          error = -1;     /* no match */
1475 1487                  break;
1476 1488          case NFS4ATTR_FREEIT:
1477 1489                  break;
1478 1490          }
1479 1491          return (error);
1480 1492  }
1481 1493  
1482 1494  /* ARGSUSED */
1483 1495  static int
1484 1496  rfs4_fattr4_files_total(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1485 1497      union nfs4_attr_u *na)
1486 1498  {
1487 1499          int     error = 0;
1488 1500  
1489 1501          if (RFS4_MANDATTR_ONLY)
1490 1502                  return (ENOTSUP);
1491 1503  
1492 1504          switch (cmd) {
1493 1505          case NFS4ATTR_SUPPORTED:
1494 1506                  if (sarg->op == NFS4ATTR_SETIT)
1495 1507                          error = EINVAL;
1496 1508                  break;          /* this attr is supported */
1497 1509          case NFS4ATTR_GETIT:
1498 1510                  if (sarg->rdattr_error && (sarg->sbp == NULL)) {
1499 1511                          error = -1;     /* may be okay if rdattr_error */
1500 1512                          break;
1501 1513                  }
1502 1514                  ASSERT(sarg->sbp != NULL);
1503 1515                  na->files_total = sarg->sbp->f_files;
1504 1516                  break;
1505 1517          case NFS4ATTR_SETIT:
1506 1518                  /*
1507 1519                   * read-only attr
1508 1520                   */
1509 1521                  error = EINVAL;
1510 1522                  break;
1511 1523          case NFS4ATTR_VERIT:
1512 1524                  ASSERT(sarg->sbp != NULL);
1513 1525                  if (sarg->sbp->f_files != na->files_total)
1514 1526                          error = -1;     /* no match */
1515 1527                  break;
1516 1528          case NFS4ATTR_FREEIT:
1517 1529                  break;
1518 1530          }
1519 1531          return (error);
1520 1532  }
1521 1533  
1522 1534  static void
1523 1535  rfs4_free_pathname4(pathname4 *pn4)
1524 1536  {
1525 1537          int i, len;
1526 1538          utf8string *utf8s;
1527 1539  
1528 1540          if (pn4 == NULL || (len = pn4->pathname4_len) == 0 ||
1529 1541              (utf8s = pn4->pathname4_val) == NULL)
1530 1542                  return;
1531 1543  
1532 1544          for (i = 0; i < len; i++, utf8s++) {
1533 1545                  if (utf8s->utf8string_val == NULL ||
1534 1546                      utf8s->utf8string_len == 0)
1535 1547                          continue;
1536 1548  
1537 1549                  kmem_free(utf8s->utf8string_val, utf8s->utf8string_len);
1538 1550                  utf8s->utf8string_val = NULL;
1539 1551          }
1540 1552  
1541 1553          kmem_free(pn4->pathname4_val,
1542 1554              sizeof (utf8string) * pn4->pathname4_len);
1543 1555          pn4->pathname4_val = 0;
1544 1556  }
1545 1557  
1546 1558  static void
1547 1559  rfs4_free_fs_location4(fs_location4 *fsl4)
1548 1560  {
1549 1561          if (fsl4 == NULL)
1550 1562                  return;
1551 1563  
1552 1564          rfs4_free_pathname4((pathname4 *)&fsl4->server_len);
1553 1565          rfs4_free_pathname4(&fsl4->rootpath);
1554 1566  }
1555 1567  
1556 1568  void
1557 1569  rfs4_free_fs_locations4(fs_locations4 *fsls4)
1558 1570  {
1559 1571          int i, len;
1560 1572          fs_location4 *fsl4;
1561 1573  
1562 1574          if (fsls4 == NULL)
1563 1575                  return;
1564 1576  
1565 1577          /* free fs_root */
1566 1578          rfs4_free_pathname4(&fsls4->fs_root);
1567 1579  
1568 1580          if ((len = fsls4->locations_len) == 0 ||
1569 1581              (fsl4 = fsls4->locations_val) == NULL)
1570 1582                  return;
1571 1583  
1572 1584          /* free fs_location4 */
1573 1585          for (i = 0; i < len; i++) {
1574 1586                  rfs4_free_fs_location4(fsl4);
1575 1587                  fsl4++;
1576 1588          }
1577 1589  
1578 1590          kmem_free(fsls4->locations_val, sizeof (fs_location4) * len);
1579 1591          fsls4->locations_val = NULL;
1580 1592  }
1581 1593  
1582 1594  /* ARGSUSED */
1583 1595  static int
1584 1596  rfs4_fattr4_fs_locations(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1585 1597      union nfs4_attr_u *na)
1586 1598  {
1587 1599          int error = 0;
1588 1600          fs_locations4 *fsl;
1589 1601  
1590 1602          if (RFS4_MANDATTR_ONLY)
1591 1603                  return (ENOTSUP);
1592 1604  
1593 1605          switch (cmd) {
1594 1606          case NFS4ATTR_SUPPORTED:
1595 1607                  if (sarg->op == NFS4ATTR_SETIT || sarg->op == NFS4ATTR_VERIT)
1596 1608                          error = EINVAL;
1597 1609                  break;  /* this attr is supported */
1598 1610  
1599 1611          case NFS4ATTR_GETIT:
1600 1612                  fsl = fetch_referral(sarg->cs->vp, sarg->cs->cr);
1601 1613                  if (fsl == NULL)
1602 1614                          (void) memset(&(na->fs_locations), 0,
1603 1615                              sizeof (fs_locations4));
1604 1616                  else {
1605 1617                          na->fs_locations = *fsl;
1606 1618                          kmem_free(fsl, sizeof (fs_locations4));
1607 1619                  }
1608 1620                  global_svstat_ptr[4][NFS_REFERRALS].value.ui64++;
1609 1621                  break;
1610 1622  
1611 1623          case NFS4ATTR_FREEIT:
1612 1624                  if (sarg->op == NFS4ATTR_SETIT || sarg->op == NFS4ATTR_VERIT)
1613 1625                          error = EINVAL;
1614 1626                  rfs4_free_fs_locations4(&na->fs_locations);
1615 1627                  break;
1616 1628  
1617 1629          case NFS4ATTR_SETIT:
1618 1630          case NFS4ATTR_VERIT:
1619 1631                  /*
1620 1632                   * read-only attr
1621 1633                   */
1622 1634                  error = EINVAL;
1623 1635                  break;
1624 1636          }
1625 1637          return (error);
1626 1638  }
1627 1639  
1628 1640  /* ARGSUSED */
1629 1641  static int
1630 1642  rfs4_fattr4_hidden(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1631 1643      union nfs4_attr_u *na)
1632 1644  {
1633 1645          return (ENOTSUP);
1634 1646  }
1635 1647  
1636 1648  /* ARGSUSED */
1637 1649  static int
1638 1650  rfs4_fattr4_homogeneous(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1639 1651      union nfs4_attr_u *na)
1640 1652  {
1641 1653          int error = 0;
1642 1654  
1643 1655          if (RFS4_MANDATTR_ONLY)
1644 1656                  return (ENOTSUP);
1645 1657  
1646 1658          switch (cmd) {
1647 1659          case NFS4ATTR_SUPPORTED:
1648 1660                  if (sarg->op == NFS4ATTR_SETIT)
1649 1661                          error = EINVAL;
1650 1662                  break;          /* this attr is supported */
1651 1663          case NFS4ATTR_GETIT:
1652 1664                  na->homogeneous = TRUE; /* XXX - need a VOP extension */
1653 1665                  break;
1654 1666          case NFS4ATTR_SETIT:
1655 1667                  /*
1656 1668                   * read-only attr
1657 1669                   */
1658 1670                  error = EINVAL;
1659 1671                  break;
1660 1672          case NFS4ATTR_VERIT:
1661 1673                  if (!na->homogeneous)
1662 1674                          error = -1;     /* no match */
1663 1675                  break;
1664 1676          case NFS4ATTR_FREEIT:
1665 1677                  break;
1666 1678          }
1667 1679          return (error);
1668 1680  }
1669 1681  
1670 1682  /* ARGSUSED */
1671 1683  static int
1672 1684  rfs4_fattr4_maxfilesize(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1673 1685      union nfs4_attr_u *na)
1674 1686  {
1675 1687          int error = 0;
1676 1688          ulong_t val;
1677 1689          fattr4_maxfilesize maxfilesize;
1678 1690  
1679 1691          if (RFS4_MANDATTR_ONLY)
1680 1692                  return (ENOTSUP);
1681 1693  
1682 1694          switch (cmd) {
1683 1695          case NFS4ATTR_SUPPORTED:
1684 1696                  if (sarg->op == NFS4ATTR_SETIT)
1685 1697                          error = EINVAL;
1686 1698                  break;          /* this attr is supported */
1687 1699          case NFS4ATTR_GETIT:
1688 1700                  if (sarg->rdattr_error && (sarg->cs->vp == NULL)) {
1689 1701                          error = -1;     /* may be okay if rdattr_error */
1690 1702                          break;
1691 1703                  }
1692 1704                  ASSERT(sarg->cs->vp != NULL);
1693 1705                  error = VOP_PATHCONF(sarg->cs->vp, _PC_FILESIZEBITS, &val,
1694 1706                      sarg->cs->cr, NULL);
1695 1707                  if (error)
1696 1708                          break;
1697 1709  
1698 1710                  /*
1699 1711                   * If the underlying file system does not support
1700 1712                   * _PC_FILESIZEBITS, return a reasonable default. Note that
1701 1713                   * error code on VOP_PATHCONF will be 0, even if the underlying
1702 1714                   * file system does not support _PC_FILESIZEBITS.
1703 1715                   */
1704 1716                  if (val == (ulong_t)-1) {
1705 1717                          na->maxfilesize = MAXOFF32_T;
1706 1718                  } else {
1707 1719                          if (val >= (sizeof (uint64_t) * 8))
1708 1720                                  na->maxfilesize = INT64_MAX;
1709 1721                          else
1710 1722                                  na->maxfilesize = ((1LL << (val - 1)) - 1);
1711 1723                  }
1712 1724                  break;
1713 1725          case NFS4ATTR_SETIT:
1714 1726                  /*
1715 1727                   * read-only attr
1716 1728                   */
1717 1729                  error = EINVAL;
1718 1730                  break;
1719 1731          case NFS4ATTR_VERIT:
1720 1732                  ASSERT(sarg->cs->vp != NULL);
1721 1733                  error = VOP_PATHCONF(sarg->cs->vp, _PC_FILESIZEBITS, &val,
1722 1734                      sarg->cs->cr, NULL);
1723 1735                  if (error)
1724 1736                          break;
1725 1737                  /*
1726 1738                   * If the underlying file system does not support
1727 1739                   * _PC_FILESIZEBITS, return a reasonable default. Note that
1728 1740                   * error code on VOP_PATHCONF will be 0, even if the underlying
1729 1741                   * file system does not support _PC_FILESIZEBITS.
1730 1742                   */
1731 1743                  if (val == (ulong_t)-1) {
1732 1744                          maxfilesize = MAXOFF32_T;
1733 1745                  } else {
1734 1746                          if (val >= (sizeof (uint64_t) * 8))
1735 1747                                  maxfilesize = INT64_MAX;
1736 1748                          else
1737 1749                                  maxfilesize = ((1LL << (val - 1)) - 1);
1738 1750                  }
1739 1751                  if (na->maxfilesize != maxfilesize)
1740 1752                          error = -1;     /* no match */
1741 1753                  break;
1742 1754          case NFS4ATTR_FREEIT:
1743 1755                  break;
1744 1756          }
1745 1757          return (error);
1746 1758  }
1747 1759  
1748 1760  /* ARGSUSED */
1749 1761  static int
1750 1762  rfs4_fattr4_maxlink(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1751 1763      union nfs4_attr_u *na)
1752 1764  {
1753 1765          int error = 0;
1754 1766          ulong_t val;
1755 1767  
1756 1768          if (RFS4_MANDATTR_ONLY)
1757 1769                  return (ENOTSUP);
1758 1770  
1759 1771          switch (cmd) {
1760 1772          case NFS4ATTR_SUPPORTED:
1761 1773                  if (sarg->op == NFS4ATTR_SETIT)
1762 1774                          error = EINVAL;
1763 1775                  break;          /* this attr is supported */
1764 1776          case NFS4ATTR_GETIT:
1765 1777                  if (sarg->rdattr_error && (sarg->cs->vp == NULL)) {
1766 1778                          error = -1;     /* may be okay if rdattr_error */
1767 1779                          break;
1768 1780                  }
1769 1781                  ASSERT(sarg->cs->vp != NULL);
1770 1782                  error = VOP_PATHCONF(sarg->cs->vp, _PC_LINK_MAX, &val,
1771 1783                      sarg->cs->cr, NULL);
1772 1784                  if (error == 0) {
1773 1785                          na->maxlink = val;
1774 1786                  }
1775 1787                  break;
1776 1788          case NFS4ATTR_SETIT:
1777 1789                  /*
1778 1790                   * read-only attr
1779 1791                   */
1780 1792                  error = EINVAL;
1781 1793                  break;
1782 1794          case NFS4ATTR_VERIT:
1783 1795                  ASSERT(sarg->cs->vp != NULL);
1784 1796                  error = VOP_PATHCONF(sarg->cs->vp, _PC_LINK_MAX, &val,
1785 1797                      sarg->cs->cr, NULL);
1786 1798                  if (!error && (na->maxlink != (uint32_t)val))
1787 1799                          error = -1;     /* no match */
1788 1800                  break;
1789 1801          case NFS4ATTR_FREEIT:
1790 1802                  break;
1791 1803          }
1792 1804          return (error);
1793 1805  }
1794 1806  
1795 1807  /* ARGSUSED */
1796 1808  static int
1797 1809  rfs4_fattr4_maxname(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1798 1810      union nfs4_attr_u *na)
1799 1811  {
1800 1812          int error = 0;
1801 1813          ulong_t val;
1802 1814  
1803 1815          if (RFS4_MANDATTR_ONLY)
1804 1816                  return (ENOTSUP);
1805 1817  
1806 1818          switch (cmd) {
1807 1819          case NFS4ATTR_SUPPORTED:
1808 1820                  if (sarg->op == NFS4ATTR_SETIT)
1809 1821                          error = EINVAL;
1810 1822                  break;          /* this attr is supported */
1811 1823          case NFS4ATTR_GETIT:
1812 1824                  if (sarg->rdattr_error && (sarg->cs->vp == NULL)) {
1813 1825                          error = -1;     /* may be okay if rdattr_error */
1814 1826                          break;
1815 1827                  }
1816 1828                  ASSERT(sarg->cs->vp != NULL);
1817 1829                  error = VOP_PATHCONF(sarg->cs->vp, _PC_NAME_MAX, &val,
1818 1830                      sarg->cs->cr, NULL);
1819 1831                  if (error == 0) {
1820 1832                          na->maxname = val;
1821 1833                  }
1822 1834                  break;
1823 1835          case NFS4ATTR_SETIT:
1824 1836                  /*
1825 1837                   * read-only attr
1826 1838                   */
1827 1839                  error = EINVAL;
1828 1840                  break;
1829 1841          case NFS4ATTR_VERIT:
1830 1842                  ASSERT(sarg->cs->vp != NULL);
1831 1843                  error = VOP_PATHCONF(sarg->cs->vp, _PC_NAME_MAX, &val,
1832 1844                      sarg->cs->cr, NULL);
1833 1845                  if (!error && (na->maxname != val))
1834 1846                          error = -1;     /* no match */
1835 1847                  break;
1836 1848          case NFS4ATTR_FREEIT:
1837 1849                  break;
1838 1850          }
1839 1851          return (error);
1840 1852  }
1841 1853  
1842 1854  /* ARGSUSED */
1843 1855  static int
1844 1856  rfs4_fattr4_maxread(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1845 1857      union nfs4_attr_u *na)
1846 1858  {
1847 1859          int error = 0;
1848 1860  
1849 1861          if (RFS4_MANDATTR_ONLY)
1850 1862                  return (ENOTSUP);
1851 1863  
1852 1864          switch (cmd) {
1853 1865          case NFS4ATTR_SUPPORTED:
1854 1866                  if (sarg->op == NFS4ATTR_SETIT)
1855 1867                          error = EINVAL;
1856 1868                  break;          /* this attr is supported */
1857 1869          case NFS4ATTR_GETIT:
1858 1870                  na->maxread = rfs4_tsize(sarg->cs->req);
1859 1871                  break;
1860 1872          case NFS4ATTR_SETIT:
1861 1873                  /*
1862 1874                   * read-only attr
1863 1875                   */
1864 1876                  error = EINVAL;
1865 1877                  break;
1866 1878          case NFS4ATTR_VERIT:
1867 1879                  if (na->maxread != rfs4_tsize(sarg->cs->req))
1868 1880                          error = -1;     /* no match */
1869 1881                  break;
1870 1882          case NFS4ATTR_FREEIT:
1871 1883                  break;
1872 1884          }
1873 1885          return (error);
1874 1886  }
1875 1887  
1876 1888  /* ARGSUSED */
1877 1889  static int
1878 1890  rfs4_fattr4_maxwrite(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1879 1891      union nfs4_attr_u *na)
1880 1892  {
1881 1893          int error = 0;
1882 1894  
1883 1895          if (RFS4_MANDATTR_ONLY)
1884 1896                  return (ENOTSUP);
1885 1897  
1886 1898          switch (cmd) {
1887 1899          case NFS4ATTR_SUPPORTED:
1888 1900                  if (sarg->op == NFS4ATTR_SETIT)
1889 1901                          error = EINVAL;
1890 1902                  break;          /* this attr is supported */
1891 1903          case NFS4ATTR_GETIT:
1892 1904                  na->maxwrite = rfs4_tsize(sarg->cs->req);
1893 1905                  break;
1894 1906          case NFS4ATTR_SETIT:
1895 1907                  /*
1896 1908                   * read-only attr
1897 1909                   */
1898 1910                  error = EINVAL;
1899 1911                  break;
1900 1912          case NFS4ATTR_VERIT:
1901 1913                  if (na->maxwrite != rfs4_tsize(sarg->cs->req))
1902 1914                          error = -1;     /* no match */
1903 1915                  break;
1904 1916          case NFS4ATTR_FREEIT:
1905 1917                  break;
1906 1918          }
1907 1919          return (error);
1908 1920  }
1909 1921  
1910 1922  /* ARGSUSED */
1911 1923  static int
1912 1924  rfs4_fattr4_mimetype(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1913 1925      union nfs4_attr_u *na)
1914 1926  {
1915 1927          return (ENOTSUP);
1916 1928  }
1917 1929  
1918 1930  /* ARGSUSED */
1919 1931  static int
1920 1932  rfs4_fattr4_mode(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1921 1933      union nfs4_attr_u *na)
1922 1934  {
1923 1935          int     error = 0;
1924 1936  
1925 1937          if (RFS4_MANDATTR_ONLY)
1926 1938                  return (ENOTSUP);
1927 1939  
1928 1940          switch (cmd) {
1929 1941          case NFS4ATTR_SUPPORTED:
1930 1942                  break;          /* this attr is supported */
1931 1943          case NFS4ATTR_GETIT:
1932 1944                  if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_MODE)) {
1933 1945                          error = -1;     /* may be okay if rdattr_error */
1934 1946                          break;
1935 1947                  }
1936 1948                  ASSERT(sarg->vap->va_mask & AT_MODE);
1937 1949                  na->mode = sarg->vap->va_mode;
1938 1950                  break;
1939 1951          case NFS4ATTR_SETIT:
1940 1952                  ASSERT(sarg->vap->va_mask & AT_MODE);
1941 1953                  sarg->vap->va_mode = na->mode;
1942 1954                  /*
1943 1955                   * If the filesystem is exported with nosuid, then mask off
1944 1956                   * the setuid and setgid bits.
1945 1957                   */
1946 1958                  if (sarg->cs->vp->v_type == VREG &&
1947 1959                      (sarg->cs->exi->exi_export.ex_flags & EX_NOSUID))
1948 1960                          sarg->vap->va_mode &= ~(VSUID | VSGID);
1949 1961                  break;
1950 1962          case NFS4ATTR_VERIT:
1951 1963                  ASSERT(sarg->vap->va_mask & AT_MODE);
1952 1964                  if (sarg->vap->va_mode != na->mode)
1953 1965                          error = -1;     /* no match */
1954 1966                  break;
1955 1967          case NFS4ATTR_FREEIT:
1956 1968                  break;
1957 1969          }
1958 1970          return (error);
1959 1971  }
1960 1972  
1961 1973  /* ARGSUSED */
1962 1974  static int
1963 1975  rfs4_fattr4_no_trunc(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1964 1976      union nfs4_attr_u *na)
1965 1977  {
1966 1978          int error = 0;
1967 1979  
1968 1980          if (RFS4_MANDATTR_ONLY)
1969 1981                  return (ENOTSUP);
1970 1982  
1971 1983          switch (cmd) {
1972 1984          case NFS4ATTR_SUPPORTED:
1973 1985                  if (sarg->op == NFS4ATTR_SETIT)
1974 1986                          error = EINVAL;
1975 1987                  break;          /* this attr is supported */
1976 1988          case NFS4ATTR_GETIT:
1977 1989                  na->no_trunc = TRUE;
1978 1990                  break;
1979 1991          case NFS4ATTR_SETIT:
1980 1992                  /*
1981 1993                   * read-only attr
1982 1994                   */
1983 1995                  error = EINVAL;
1984 1996                  break;
1985 1997          case NFS4ATTR_VERIT:
1986 1998                  if (!na->no_trunc)
1987 1999                          error = -1;     /* no match */
1988 2000                  break;
1989 2001          case NFS4ATTR_FREEIT:
1990 2002                  break;
1991 2003          }
1992 2004          return (error);
1993 2005  }
1994 2006  
1995 2007  /* ARGSUSED */
1996 2008  static int
1997 2009  rfs4_fattr4_numlinks(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
1998 2010      union nfs4_attr_u *na)
1999 2011  {
2000 2012          int     error = 0;
2001 2013  
2002 2014          if (RFS4_MANDATTR_ONLY)
2003 2015                  return (ENOTSUP);
2004 2016  
2005 2017          switch (cmd) {
2006 2018          case NFS4ATTR_SUPPORTED:
2007 2019                  if (sarg->op == NFS4ATTR_SETIT)
2008 2020                          error = EINVAL;
2009 2021                  break;          /* this attr is supported */
2010 2022          case NFS4ATTR_GETIT:
2011 2023                  if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_NLINK)) {
2012 2024                          error = -1;     /* may be okay if rdattr_error */
2013 2025                          break;
2014 2026                  }
2015 2027                  ASSERT(sarg->vap->va_mask & AT_NLINK);
2016 2028                  na->numlinks = sarg->vap->va_nlink;
2017 2029                  break;
2018 2030          case NFS4ATTR_SETIT:
2019 2031                  /*
2020 2032                   * read-only attr
2021 2033                   */
2022 2034                  error = EINVAL;
2023 2035                  break;
2024 2036          case NFS4ATTR_VERIT:
2025 2037                  ASSERT(sarg->vap->va_mask & AT_NLINK);
2026 2038                  if (sarg->vap->va_nlink != na->numlinks)
2027 2039                          error = -1;     /* no match */
2028 2040                  break;
2029 2041          case NFS4ATTR_FREEIT:
2030 2042                  break;
2031 2043          }
2032 2044          return (error);
2033 2045  }
2034 2046  
2035 2047  /* ARGSUSED */
2036 2048  static int
2037 2049  rfs4_fattr4_owner(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2038 2050      union nfs4_attr_u *na)
2039 2051  {
2040 2052          int     error = 0;
2041 2053          uid_t   uid;
2042 2054  
2043 2055          if (RFS4_MANDATTR_ONLY)
2044 2056                  return (ENOTSUP);
2045 2057  
2046 2058          switch (cmd) {
2047 2059          case NFS4ATTR_SUPPORTED:
2048 2060                  break;          /* this attr is supported */
2049 2061          case NFS4ATTR_GETIT:
2050 2062                  if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_UID)) {
2051 2063                          error = -1;     /* may be okay if rdattr_error */
2052 2064                          break;
2053 2065                  }
2054 2066                  ASSERT(sarg->vap->va_mask & AT_UID);
2055 2067  
2056 2068                  /*
2057 2069                   * There are well defined polices for what happens on server-
2058 2070                   * side GETATTR when uid to attribute string conversion cannot
2059 2071                   * occur. Please refer to nfs4_idmap.c for details.
2060 2072                   */
2061 2073                  error = nfs_idmap_uid_str(sarg->vap->va_uid, &na->owner, TRUE);
2062 2074                  switch (error) {
2063 2075                  case ECONNREFUSED:
2064 2076                          error = NFS4ERR_DELAY;
2065 2077                          break;
2066 2078                  default:
2067 2079                          break;
2068 2080                  }
2069 2081                  break;
2070 2082  
2071 2083          case NFS4ATTR_SETIT:
2072 2084                  ASSERT(sarg->vap->va_mask & AT_UID);
2073 2085  
2074 2086                  /*
2075 2087                   * There are well defined policies for what happens on server-
2076 2088                   * side SETATTR of 'owner' when a "user@domain" mapping cannot
2077 2089                   * occur. Please refer to nfs4_idmap.c for details.
2078 2090                   *
2079 2091                   * Any other errors, such as the mapping not being found by
2080 2092                   * nfsmapid(1m), and interrupted clnt_call, etc, will result
2081 2093                   * in NFS4ERR_BADOWNER.
2082 2094                   *
2083 2095                   * XXX need to return consistent errors, perhaps all
2084 2096                   * server side attribute routines should return NFS4ERR*.
2085 2097                   */
2086 2098                  error = nfs_idmap_str_uid(&na->owner, &sarg->vap->va_uid, TRUE);
2087 2099                  switch (error) {
2088 2100                  case NFS4_OK:
2089 2101                  case ENOTSUP:
2090 2102                          /*
2091 2103                           * Ignore warning that we are the
2092 2104                           * nfsmapid (can't happen on srv)
2093 2105                           */
2094 2106                          error = 0;
2095 2107                          MSG_PRT_DEBUG = FALSE;
2096 2108                          break;
2097 2109  
2098 2110                  case ECOMM:
2099 2111                  case ECONNREFUSED:
2100 2112                          if (!MSG_PRT_DEBUG) {
2101 2113                                  /*
2102 2114                                   * printed just once per daemon death,
2103 2115                                   * inform the user and then stay silent
2104 2116                                   */
2105 2117                                  cmn_err(CE_WARN, "!Unable to contact "
2106 2118                                      "nfsmapid");
2107 2119                                  MSG_PRT_DEBUG = TRUE;
2108 2120                          }
2109 2121                          error = NFS4ERR_DELAY;
2110 2122                          break;
2111 2123  
2112 2124                  case EINVAL:
2113 2125                          error = NFS4ERR_INVAL;
2114 2126                          break;
2115 2127  
2116 2128                  default:
2117 2129                          error = NFS4ERR_BADOWNER;
2118 2130                          break;
2119 2131                  }
2120 2132                  break;
2121 2133  
2122 2134          case NFS4ATTR_VERIT:
2123 2135                  ASSERT(sarg->vap->va_mask & AT_UID);
2124 2136                  error = nfs_idmap_str_uid(&na->owner, &uid, TRUE);
2125 2137                  /*
2126 2138                   * Ignore warning that we are the nfsmapid (can't happen on srv)
2127 2139                   */
2128 2140                  if (error == ENOTSUP)
2129 2141                          error = 0;
2130 2142                  if (error)
2131 2143                          error = -1;     /* no match */
2132 2144                  else if (sarg->vap->va_uid != uid)
2133 2145                          error = -1;     /* no match */
2134 2146                  break;
2135 2147          case NFS4ATTR_FREEIT:
2136 2148                  if (sarg->op == NFS4ATTR_GETIT) {
2137 2149                          if (na->owner.utf8string_val) {
2138 2150                                  UTF8STRING_FREE(na->owner)
2139 2151                                  bzero(&na->owner, sizeof (na->owner));
2140 2152                          }
2141 2153                  }
2142 2154                  break;
2143 2155          }
2144 2156          return (error);
2145 2157  }
2146 2158  
2147 2159  /* ARGSUSED */
2148 2160  static int
2149 2161  rfs4_fattr4_owner_group(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2150 2162      union nfs4_attr_u *na)
2151 2163  {
2152 2164          int     error = 0;
2153 2165          gid_t   gid;
2154 2166  
2155 2167          if (RFS4_MANDATTR_ONLY)
2156 2168                  return (ENOTSUP);
2157 2169  
2158 2170          switch (cmd) {
2159 2171          case NFS4ATTR_SUPPORTED:
2160 2172                  break;          /* this attr is supported */
2161 2173          case NFS4ATTR_GETIT:
2162 2174                  if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_GID)) {
2163 2175                          error = -1;     /* may be okay if rdattr_error */
2164 2176                          break;
2165 2177                  }
2166 2178                  ASSERT(sarg->vap->va_mask & AT_GID);
2167 2179  
2168 2180                  /*
2169 2181                   * There are well defined polices for what happens on server-
2170 2182                   * side GETATTR when gid to attribute string conversion cannot
2171 2183                   * occur. Please refer to nfs4_idmap.c for details.
2172 2184                   */
2173 2185                  error = nfs_idmap_gid_str(sarg->vap->va_gid, &na->owner_group,
2174 2186                      TRUE);
2175 2187                  switch (error) {
2176 2188                  case ECONNREFUSED:
2177 2189                          error = NFS4ERR_DELAY;
2178 2190                          break;
2179 2191                  default:
2180 2192                          break;
2181 2193                  }
2182 2194                  break;
2183 2195  
2184 2196          case NFS4ATTR_SETIT:
2185 2197                  ASSERT(sarg->vap->va_mask & AT_GID);
2186 2198  
2187 2199                  /*
2188 2200                   * There are well defined policies for what happens on server-
2189 2201                   * side SETATTR of 'owner_group' when a "group@domain" mapping
2190 2202                   * cannot occur. Please refer to nfs4_idmap.c for details.
2191 2203                   *
2192 2204                   * Any other errors, such as the mapping not being found by
2193 2205                   * nfsmapid(1m), and interrupted clnt_call, etc, will result
2194 2206                   * in NFS4ERR_BADOWNER.
2195 2207                   *
2196 2208                   * XXX need to return consistent errors, perhaps all
2197 2209                   * server side attribute routines should return NFS4ERR*.
2198 2210                   */
2199 2211                  error = nfs_idmap_str_gid(&na->owner_group, &sarg->vap->va_gid,
2200 2212                      TRUE);
2201 2213                  switch (error) {
2202 2214                  case NFS4_OK:
2203 2215                  case ENOTSUP:
2204 2216                          /*
2205 2217                           * Ignore warning that we are the
2206 2218                           * nfsmapid (can't happen on srv)
2207 2219                           */
2208 2220                          error = 0;
2209 2221                          MSG_PRT_DEBUG = FALSE;
2210 2222                          break;
2211 2223  
2212 2224                  case ECOMM:
2213 2225                  case ECONNREFUSED:
2214 2226                          if (!MSG_PRT_DEBUG) {
2215 2227                                  /*
2216 2228                                   * printed just once per daemon death,
2217 2229                                   * inform the user and then stay silent
2218 2230                                   */
2219 2231                                  cmn_err(CE_WARN, "!Unable to contact "
2220 2232                                      "nfsmapid");
2221 2233                                  MSG_PRT_DEBUG = TRUE;
2222 2234                          }
2223 2235                          error = NFS4ERR_DELAY;
2224 2236                          break;
2225 2237  
2226 2238                  case EINVAL:
2227 2239                          error = NFS4ERR_INVAL;
2228 2240                          break;
2229 2241  
2230 2242                  default:
2231 2243                          error = NFS4ERR_BADOWNER;
2232 2244                          break;
2233 2245                  }
2234 2246                  break;
2235 2247  
2236 2248          case NFS4ATTR_VERIT:
2237 2249                  ASSERT(sarg->vap->va_mask & AT_GID);
2238 2250                  error = nfs_idmap_str_gid(&na->owner_group, &gid, TRUE);
2239 2251                  /*
2240 2252                   * Ignore warning that we are the nfsmapid (can't happen on srv)
2241 2253                   */
2242 2254                  if (error == ENOTSUP)
2243 2255                          error = 0;
2244 2256                  if (error)
2245 2257                          error = -1;     /* no match */
2246 2258                  else if (sarg->vap->va_gid != gid)
2247 2259                          error = -1;     /* no match */
2248 2260                  break;
2249 2261          case NFS4ATTR_FREEIT:
2250 2262                  if (sarg->op == NFS4ATTR_GETIT) {
2251 2263                          if (na->owner_group.utf8string_val) {
2252 2264                                  UTF8STRING_FREE(na->owner_group)
2253 2265                                  bzero(&na->owner_group,
2254 2266                                      sizeof (na->owner_group));
2255 2267                          }
2256 2268                  }
2257 2269                  break;
2258 2270          }
2259 2271          return (error);
2260 2272  }
2261 2273  
2262 2274  /* XXX - quota attributes should be supportable on Solaris 2 */
2263 2275  /* ARGSUSED */
2264 2276  static int
2265 2277  rfs4_fattr4_quota_avail_hard(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2266 2278      union nfs4_attr_u *na)
2267 2279  {
2268 2280          return (ENOTSUP);
2269 2281  }
2270 2282  
2271 2283  /* ARGSUSED */
2272 2284  static int
2273 2285  rfs4_fattr4_quota_avail_soft(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2274 2286      union nfs4_attr_u *na)
2275 2287  {
2276 2288          return (ENOTSUP);
2277 2289  }
2278 2290  
2279 2291  /* ARGSUSED */
2280 2292  static int
2281 2293  rfs4_fattr4_quota_used(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2282 2294      union nfs4_attr_u *na)
2283 2295  {
2284 2296          return (ENOTSUP);
2285 2297  }
2286 2298  
2287 2299  /* ARGSUSED */
2288 2300  static int
2289 2301  rfs4_fattr4_rawdev(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2290 2302      union nfs4_attr_u *na)
2291 2303  {
2292 2304          int     error = 0;
2293 2305  
2294 2306          if (RFS4_MANDATTR_ONLY)
2295 2307                  return (ENOTSUP);
2296 2308  
2297 2309          switch (cmd) {
2298 2310          case NFS4ATTR_SUPPORTED:
2299 2311                  if (sarg->op == NFS4ATTR_SETIT)
2300 2312                          error = EINVAL;
2301 2313                  break;          /* this attr is supported */
2302 2314          case NFS4ATTR_GETIT:
2303 2315                  if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_RDEV)) {
2304 2316                          error = -1;     /* may be okay if rdattr_error */
2305 2317                          break;
2306 2318                  }
2307 2319                  ASSERT(sarg->vap->va_mask & AT_RDEV);
2308 2320                  na->rawdev.specdata1 =  (uint32)getmajor(sarg->vap->va_rdev);
2309 2321                  na->rawdev.specdata2 =  (uint32)getminor(sarg->vap->va_rdev);
2310 2322                  break;
2311 2323          case NFS4ATTR_SETIT:
2312 2324                  /*
2313 2325                   * read-only attr
2314 2326                   */
2315 2327                  error = EINVAL;
2316 2328                  break;
2317 2329          case NFS4ATTR_VERIT:
2318 2330                  ASSERT(sarg->vap->va_mask & AT_RDEV);
2319 2331                  if ((na->rawdev.specdata1 !=
2320 2332                      (uint32)getmajor(sarg->vap->va_rdev)) ||
2321 2333                      (na->rawdev.specdata2 !=
2322 2334                      (uint32)getminor(sarg->vap->va_rdev)))
2323 2335                          error = -1;     /* no match */
2324 2336                  break;
2325 2337          case NFS4ATTR_FREEIT:
2326 2338                  break;
2327 2339          }
2328 2340          return (error);
2329 2341  }
2330 2342  
2331 2343  /* ARGSUSED */
2332 2344  static int
2333 2345  rfs4_fattr4_space_avail(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2334 2346      union nfs4_attr_u *na)
2335 2347  {
2336 2348          int     error = 0;
2337 2349  
2338 2350          if (RFS4_MANDATTR_ONLY)
2339 2351                  return (ENOTSUP);
2340 2352  
2341 2353          switch (cmd) {
2342 2354          case NFS4ATTR_SUPPORTED:
2343 2355                  if (sarg->op == NFS4ATTR_SETIT)
2344 2356                          error = EINVAL;
2345 2357                  break;          /* this attr is supported */
2346 2358          case NFS4ATTR_GETIT:
2347 2359                  if (sarg->rdattr_error && (sarg->sbp == NULL)) {
2348 2360                          error = -1;     /* may be okay if rdattr_error */
2349 2361                          break;
2350 2362                  }
2351 2363                  ASSERT(sarg->sbp != NULL);
2352 2364                  if (sarg->sbp->f_bavail != (fsblkcnt64_t)-1) {
2353 2365                          na->space_avail =
2354 2366                              (fattr4_space_avail) sarg->sbp->f_frsize *
2355 2367                              (fattr4_space_avail) sarg->sbp->f_bavail;
2356 2368                  } else {
2357 2369                          na->space_avail =
2358 2370                              (fattr4_space_avail) sarg->sbp->f_bavail;
2359 2371                  }
2360 2372                  break;
2361 2373          case NFS4ATTR_SETIT:
2362 2374                  /*
2363 2375                   * read-only attr
2364 2376                   */
2365 2377                  error = EINVAL;
2366 2378                  break;
2367 2379          case NFS4ATTR_VERIT:
2368 2380                  ASSERT(sarg->sbp != NULL);
2369 2381                  if (sarg->sbp->f_bavail != na->space_avail)
2370 2382                          error = -1;     /* no match */
2371 2383                  break;
2372 2384          case NFS4ATTR_FREEIT:
2373 2385                  break;
2374 2386          }
2375 2387          return (error);
2376 2388  }
2377 2389  
2378 2390  /* ARGSUSED */
2379 2391  static int
2380 2392  rfs4_fattr4_space_free(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2381 2393      union nfs4_attr_u *na)
2382 2394  {
2383 2395          int     error = 0;
2384 2396  
2385 2397          if (RFS4_MANDATTR_ONLY)
2386 2398                  return (ENOTSUP);
2387 2399  
2388 2400          switch (cmd) {
2389 2401          case NFS4ATTR_SUPPORTED:
2390 2402                  if (sarg->op == NFS4ATTR_SETIT)
2391 2403                          error = EINVAL;
2392 2404                  break;          /* this attr is supported */
2393 2405          case NFS4ATTR_GETIT:
2394 2406                  if (sarg->rdattr_error && (sarg->sbp == NULL)) {
2395 2407                          error = -1;     /* may be okay if rdattr_error */
2396 2408                          break;
2397 2409                  }
2398 2410                  ASSERT(sarg->sbp != NULL);
2399 2411                  if (sarg->sbp->f_bfree != (fsblkcnt64_t)-1) {
2400 2412                          na->space_free =
2401 2413                              (fattr4_space_free) sarg->sbp->f_frsize *
2402 2414                              (fattr4_space_free) sarg->sbp->f_bfree;
2403 2415                  } else {
2404 2416                          na->space_free =
2405 2417                              (fattr4_space_free) sarg->sbp->f_bfree;
2406 2418                  }
2407 2419                  break;
2408 2420          case NFS4ATTR_SETIT:
2409 2421                  /*
2410 2422                   * read-only attr
2411 2423                   */
2412 2424                  error = EINVAL;
2413 2425                  break;
2414 2426          case NFS4ATTR_VERIT:
2415 2427                  ASSERT(sarg->sbp != NULL);
2416 2428                  if (sarg->sbp->f_bfree != na->space_free)
2417 2429                          error = -1;     /* no match */
2418 2430                  break;
2419 2431          case NFS4ATTR_FREEIT:
2420 2432                  break;
2421 2433          }
2422 2434          return (error);
2423 2435  }
2424 2436  
2425 2437  /* ARGSUSED */
2426 2438  static int
2427 2439  rfs4_fattr4_space_total(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2428 2440      union nfs4_attr_u *na)
2429 2441  {
2430 2442          int     error = 0;
2431 2443  
2432 2444          if (RFS4_MANDATTR_ONLY)
2433 2445                  return (ENOTSUP);
2434 2446  
2435 2447          switch (cmd) {
2436 2448          case NFS4ATTR_SUPPORTED:
2437 2449                  if (sarg->op == NFS4ATTR_SETIT)
2438 2450                          error = EINVAL;
2439 2451                  break;          /* this attr is supported */
2440 2452          case NFS4ATTR_GETIT:
2441 2453                  if (sarg->rdattr_error_req && (sarg->sbp == NULL)) {
2442 2454                          error = -1;     /* may be okay if rdattr_error */
2443 2455                          break;
2444 2456                  }
2445 2457                  ASSERT(sarg->sbp != NULL);
2446 2458                  if (sarg->sbp->f_blocks != (fsblkcnt64_t)-1) {
2447 2459                          na->space_total =
2448 2460                              (fattr4_space_total) sarg->sbp->f_frsize *
2449 2461                              (fattr4_space_total) sarg->sbp->f_blocks;
2450 2462                  } else {
2451 2463                          na->space_total =
2452 2464                              (fattr4_space_total) sarg->sbp->f_blocks;
2453 2465                  }
2454 2466                  break;
2455 2467          case NFS4ATTR_SETIT:
2456 2468                  /*
2457 2469                   * read-only attr
2458 2470                   */
2459 2471                  error = EINVAL;
2460 2472                  break;
2461 2473          case NFS4ATTR_VERIT:
2462 2474                  ASSERT(sarg->sbp != NULL);
2463 2475                  if (sarg->sbp->f_blocks != na->space_total)
2464 2476                          error = -1;     /* no match */
2465 2477                  break;
2466 2478          case NFS4ATTR_FREEIT:
2467 2479                  break;
2468 2480          }
2469 2481          return (error);
2470 2482  }
2471 2483  
2472 2484  /* ARGSUSED */
2473 2485  static int
2474 2486  rfs4_fattr4_space_used(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2475 2487      union nfs4_attr_u *na)
2476 2488  {
2477 2489          int     error = 0;
2478 2490  
2479 2491          if (RFS4_MANDATTR_ONLY)
2480 2492                  return (ENOTSUP);
2481 2493  
2482 2494          switch (cmd) {
2483 2495          case NFS4ATTR_SUPPORTED:
2484 2496                  if (sarg->op == NFS4ATTR_SETIT)
2485 2497                          error = EINVAL;
2486 2498                  break;          /* this attr is supported */
2487 2499          case NFS4ATTR_GETIT:
2488 2500                  if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_NBLOCKS)) {
2489 2501                          error = -1;     /* may be okay if rdattr_error */
2490 2502                          break;
2491 2503                  }
2492 2504                  ASSERT(sarg->vap->va_mask & AT_NBLOCKS);
2493 2505                  na->space_used =  (fattr4_space_used) DEV_BSIZE *
2494 2506                      (fattr4_space_used) sarg->vap->va_nblocks;
2495 2507                  break;
2496 2508          case NFS4ATTR_SETIT:
2497 2509                  /*
2498 2510                   * read-only attr
2499 2511                   */
2500 2512                  error = EINVAL;
2501 2513                  break;
2502 2514          case NFS4ATTR_VERIT:
2503 2515                  ASSERT(sarg->vap->va_mask & AT_NBLOCKS);
2504 2516                  if (sarg->vap->va_nblocks != na->space_used)
2505 2517                          error = -1;     /* no match */
2506 2518                  break;
2507 2519          case NFS4ATTR_FREEIT:
2508 2520                  break;
2509 2521          }
2510 2522          return (error);
2511 2523  }
2512 2524  
2513 2525  /* ARGSUSED */
2514 2526  static int
2515 2527  rfs4_fattr4_system(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2516 2528      union nfs4_attr_u *na)
2517 2529  {
2518 2530          return (ENOTSUP);
2519 2531  }
2520 2532  
2521 2533  /* ARGSUSED */
2522 2534  static int
2523 2535  rfs4_fattr4_time_access(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2524 2536      union nfs4_attr_u *na)
2525 2537  {
2526 2538          int     error = 0;
2527 2539          timestruc_t atime;
2528 2540  
2529 2541          if (RFS4_MANDATTR_ONLY)
2530 2542                  return (ENOTSUP);
2531 2543  
2532 2544          switch (cmd) {
2533 2545          case NFS4ATTR_SUPPORTED:
2534 2546                  if (sarg->op == NFS4ATTR_SETIT)
2535 2547                          error = EINVAL;
2536 2548                  break;          /* this attr is supported */
2537 2549          case NFS4ATTR_GETIT:
2538 2550                  if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_ATIME)) {
2539 2551                          error = -1;     /* may be okay if rdattr_error */
2540 2552                          break;
2541 2553                  }
2542 2554                  ASSERT(sarg->vap->va_mask & AT_ATIME);
2543 2555                  error = nfs4_time_vton(&sarg->vap->va_atime, &na->time_access);
2544 2556                  break;
2545 2557          case NFS4ATTR_SETIT:
2546 2558                  /*
2547 2559                   * read-only attr
2548 2560                   */
2549 2561                  error = EINVAL;
2550 2562                  break;
2551 2563          case NFS4ATTR_VERIT:
2552 2564                  ASSERT(sarg->vap->va_mask & AT_ATIME);
2553 2565                  error = nfs4_time_ntov(&na->time_access, &atime);
2554 2566                  if (error)
2555 2567                          break;
2556 2568                  if (bcmp(&atime, &sarg->vap->va_atime, sizeof (atime)))
2557 2569                          error = -1;     /* no match */
2558 2570                  break;
2559 2571          case NFS4ATTR_FREEIT:
2560 2572                  break;
2561 2573          }
2562 2574          return (error);
2563 2575  }
2564 2576  
2565 2577  /*
2566 2578   * XXX - need to support the setting of access time
2567 2579   */
2568 2580  /* ARGSUSED */
2569 2581  static int
2570 2582  rfs4_fattr4_time_access_set(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2571 2583      union nfs4_attr_u *na)
2572 2584  {
2573 2585          int     error = 0;
2574 2586          settime4 *ta;
2575 2587  
2576 2588          if (RFS4_MANDATTR_ONLY)
2577 2589                  return (ENOTSUP);
2578 2590  
2579 2591          switch (cmd) {
2580 2592          case NFS4ATTR_SUPPORTED:
2581 2593                  if ((sarg->op == NFS4ATTR_GETIT) ||
2582 2594                      (sarg->op == NFS4ATTR_VERIT))
2583 2595                          error = EINVAL;
2584 2596                  break;          /* this attr is supported */
2585 2597          case NFS4ATTR_GETIT:
2586 2598          case NFS4ATTR_VERIT:
2587 2599                  /*
2588 2600                   * write only attr
2589 2601                   */
2590 2602                  error = EINVAL;
2591 2603                  break;
2592 2604          case NFS4ATTR_SETIT:
2593 2605                  ASSERT(sarg->vap->va_mask & AT_ATIME);
2594 2606                  /*
2595 2607                   * Set access time (by server or by client)
2596 2608                   */
2597 2609                  ta = &na->time_access_set;
2598 2610                  if (ta->set_it == SET_TO_CLIENT_TIME4) {
2599 2611                          error = nfs4_time_ntov(&ta->time, &sarg->vap->va_atime);
2600 2612                  } else if (ta->set_it == SET_TO_SERVER_TIME4) {
2601 2613                          gethrestime(&sarg->vap->va_atime);
2602 2614                  } else {
2603 2615                          error = EINVAL;
2604 2616                  }
2605 2617                  break;
2606 2618          case NFS4ATTR_FREEIT:
2607 2619                  break;
2608 2620          }
2609 2621          return (error);
2610 2622  }
2611 2623  
2612 2624  /* ARGSUSED */
2613 2625  static int
2614 2626  rfs4_fattr4_time_backup(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2615 2627      union nfs4_attr_u *na)
2616 2628  {
2617 2629          return (ENOTSUP);
2618 2630  }
2619 2631  
2620 2632  /* ARGSUSED */
2621 2633  static int
2622 2634  rfs4_fattr4_time_create(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2623 2635      union nfs4_attr_u *na)
2624 2636  {
2625 2637          return (ENOTSUP);
2626 2638  }
2627 2639  
2628 2640  /* ARGSUSED */
2629 2641  static int
2630 2642  rfs4_fattr4_time_delta(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2631 2643      union nfs4_attr_u *na)
2632 2644  {
2633 2645          int error = 0;
2634 2646  
2635 2647          if (RFS4_MANDATTR_ONLY)
2636 2648                  return (ENOTSUP);
2637 2649  
2638 2650          switch (cmd) {
2639 2651          case NFS4ATTR_SUPPORTED:
2640 2652                  if (sarg->op == NFS4ATTR_SETIT)
2641 2653                          error = EINVAL;
2642 2654                  break;          /* this attr is supported */
2643 2655          case NFS4ATTR_GETIT:
2644 2656                  na->time_delta.seconds = 0;
2645 2657                  na->time_delta.nseconds = 1000;
2646 2658                  break;
2647 2659          case NFS4ATTR_SETIT:
2648 2660                  /*
2649 2661                   * write only attr
2650 2662                   */
2651 2663                  error = EINVAL;
2652 2664                  break;
2653 2665          case NFS4ATTR_VERIT:
2654 2666                  if ((na->time_delta.seconds != 0) ||
2655 2667                      (na->time_delta.nseconds != 1000))
2656 2668                          error = -1;     /* no match */
2657 2669                  break;
2658 2670          case NFS4ATTR_FREEIT:
2659 2671                  break;
2660 2672          }
2661 2673          return (error);
2662 2674  }
2663 2675  
2664 2676  /* ARGSUSED */
2665 2677  static int
2666 2678  rfs4_fattr4_time_metadata(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2667 2679      union nfs4_attr_u *na)
2668 2680  {
2669 2681          int     error = 0;
2670 2682          timestruc_t ctime;
2671 2683  
2672 2684          if (RFS4_MANDATTR_ONLY)
2673 2685                  return (ENOTSUP);
2674 2686  
2675 2687          switch (cmd) {
2676 2688          case NFS4ATTR_SUPPORTED:
2677 2689                  if (sarg->op == NFS4ATTR_SETIT)
2678 2690                          error = EINVAL;
2679 2691                  break;          /* this attr is supported */
2680 2692          case NFS4ATTR_GETIT:
2681 2693                  if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_CTIME)) {
2682 2694                          error = -1;     /* may be okay if rdattr_error */
2683 2695                          break;
2684 2696                  }
2685 2697                  ASSERT(sarg->vap->va_mask & AT_CTIME);
2686 2698                  error = nfs4_time_vton(&sarg->vap->va_ctime,
2687 2699                      &na->time_metadata);
2688 2700                  break;
2689 2701          case NFS4ATTR_SETIT:
2690 2702                  /*
2691 2703                   * read-only attr
2692 2704                   */
2693 2705                  error = EINVAL;
2694 2706                  break;
2695 2707          case NFS4ATTR_VERIT:
2696 2708                  ASSERT(sarg->vap->va_mask & AT_CTIME);
2697 2709                  error = nfs4_time_ntov(&na->time_metadata, &ctime);
2698 2710                  if (error)
2699 2711                          break;
2700 2712                  if (bcmp(&ctime, &sarg->vap->va_ctime, sizeof (ctime)))
2701 2713                          error = -1;     /* no match */
2702 2714                  break;
2703 2715          case NFS4ATTR_FREEIT:
2704 2716                  break;
2705 2717          }
2706 2718          return (error);
2707 2719  }
2708 2720  
2709 2721  /* ARGSUSED */
2710 2722  static int
2711 2723  rfs4_fattr4_time_modify(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2712 2724      union nfs4_attr_u *na)
2713 2725  {
2714 2726          int     error = 0;
2715 2727          timestruc_t mtime;
2716 2728  
2717 2729          if (RFS4_MANDATTR_ONLY)
2718 2730                  return (ENOTSUP);
2719 2731  
2720 2732          switch (cmd) {
2721 2733          case NFS4ATTR_SUPPORTED:
2722 2734                  if (sarg->op == NFS4ATTR_SETIT)
2723 2735                          error = EINVAL;
2724 2736                  break;          /* this attr is supported */
2725 2737          case NFS4ATTR_GETIT:
2726 2738                  if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_MTIME)) {
2727 2739                          error = -1;     /* may be okay if rdattr_error */
2728 2740                          break;
2729 2741                  }
2730 2742                  ASSERT(sarg->vap->va_mask & AT_MTIME);
2731 2743                  error = nfs4_time_vton(&sarg->vap->va_mtime, &na->time_modify);
2732 2744                  break;
2733 2745          case NFS4ATTR_SETIT:
2734 2746                  /*
2735 2747                   * read-only attr
2736 2748                   */
2737 2749                  error = EINVAL;
2738 2750                  break;
2739 2751          case NFS4ATTR_VERIT:
2740 2752                  ASSERT(sarg->vap->va_mask & AT_MTIME);
2741 2753                  error = nfs4_time_ntov(&na->time_modify, &mtime);
2742 2754                  if (error)
2743 2755                          break;
2744 2756                  if (bcmp(&mtime, &sarg->vap->va_mtime, sizeof (mtime)))
2745 2757                          error = -1;     /* no match */
2746 2758                  break;
2747 2759          case NFS4ATTR_FREEIT:
2748 2760                  break;
2749 2761          }
2750 2762          return (error);
2751 2763  }
2752 2764  
2753 2765  /*
2754 2766   * XXX - need to add support for setting modify time
2755 2767   */
2756 2768  /* ARGSUSED */
2757 2769  static int
2758 2770  rfs4_fattr4_time_modify_set(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg,
2759 2771      union nfs4_attr_u *na)
2760 2772  {
2761 2773          int     error = 0;
2762 2774          settime4 *tm;
2763 2775  
2764 2776          if (RFS4_MANDATTR_ONLY)
2765 2777                  return (ENOTSUP);
2766 2778  
2767 2779          switch (cmd) {
2768 2780          case NFS4ATTR_SUPPORTED:
2769 2781                  if ((sarg->op == NFS4ATTR_GETIT) ||
2770 2782                      (sarg->op == NFS4ATTR_VERIT))
2771 2783                          error = EINVAL;
2772 2784                  break;          /* this attr is supported */
2773 2785          case NFS4ATTR_GETIT:
2774 2786          case NFS4ATTR_VERIT:
2775 2787                  /*
2776 2788                   * write only attr
2777 2789                   */
2778 2790                  error = EINVAL;
2779 2791                  break;
2780 2792          case NFS4ATTR_SETIT:
2781 2793                  ASSERT(sarg->vap->va_mask & AT_MTIME);
2782 2794                  /*
2783 2795                   * Set modify time (by server or by client)
2784 2796                   */
2785 2797                  tm = &na->time_modify_set;
2786 2798                  if (tm->set_it == SET_TO_CLIENT_TIME4) {
2787 2799                          error = nfs4_time_ntov(&tm->time, &sarg->vap->va_mtime);
2788 2800                          sarg->flag = ATTR_UTIME;
2789 2801                  } else if (tm->set_it == SET_TO_SERVER_TIME4) {
2790 2802                          gethrestime(&sarg->vap->va_mtime);
2791 2803                  } else {
2792 2804                          error = EINVAL;
2793 2805                  }
2794 2806                  break;
2795 2807          case NFS4ATTR_FREEIT:
2796 2808                  break;
2797 2809          }
2798 2810          return (error);
2799 2811  }
2800 2812  
2801 2813  
2802 2814  static void
2803 2815  rfs4_ntov_init(void)
2804 2816  {
2805 2817          /* index must be same as corresponding FATTR4_* define */
2806 2818          nfs4_ntov_map[0].sv_getit = rfs4_fattr4_supported_attrs;
2807 2819          nfs4_ntov_map[1].sv_getit = rfs4_fattr4_type;
2808 2820          nfs4_ntov_map[2].sv_getit = rfs4_fattr4_fh_expire_type;
2809 2821          nfs4_ntov_map[3].sv_getit = rfs4_fattr4_change;
2810 2822          nfs4_ntov_map[4].sv_getit = rfs4_fattr4_size;
2811 2823          nfs4_ntov_map[5].sv_getit = rfs4_fattr4_link_support;
2812 2824          nfs4_ntov_map[6].sv_getit = rfs4_fattr4_symlink_support;
2813 2825          nfs4_ntov_map[7].sv_getit = rfs4_fattr4_named_attr;
2814 2826          nfs4_ntov_map[8].sv_getit = rfs4_fattr4_fsid;
2815 2827          nfs4_ntov_map[9].sv_getit = rfs4_fattr4_unique_handles;
2816 2828          nfs4_ntov_map[10].sv_getit = rfs4_fattr4_lease_time;
2817 2829          nfs4_ntov_map[11].sv_getit = rfs4_fattr4_rdattr_error;
2818 2830          nfs4_ntov_map[12].sv_getit = rfs4_fattr4_acl;
2819 2831          nfs4_ntov_map[13].sv_getit = rfs4_fattr4_aclsupport;
2820 2832          nfs4_ntov_map[14].sv_getit = rfs4_fattr4_archive;
2821 2833          nfs4_ntov_map[15].sv_getit = rfs4_fattr4_cansettime;
2822 2834          nfs4_ntov_map[16].sv_getit = rfs4_fattr4_case_insensitive;
2823 2835          nfs4_ntov_map[17].sv_getit = rfs4_fattr4_case_preserving;
2824 2836          nfs4_ntov_map[18].sv_getit = rfs4_fattr4_chown_restricted;
2825 2837          nfs4_ntov_map[19].sv_getit = rfs4_fattr4_filehandle;
2826 2838          nfs4_ntov_map[20].sv_getit = rfs4_fattr4_fileid;
2827 2839          nfs4_ntov_map[21].sv_getit = rfs4_fattr4_files_avail;
2828 2840          nfs4_ntov_map[22].sv_getit = rfs4_fattr4_files_free;
2829 2841          nfs4_ntov_map[23].sv_getit = rfs4_fattr4_files_total;
2830 2842          nfs4_ntov_map[24].sv_getit = rfs4_fattr4_fs_locations;
2831 2843          nfs4_ntov_map[25].sv_getit = rfs4_fattr4_hidden;
2832 2844          nfs4_ntov_map[26].sv_getit = rfs4_fattr4_homogeneous;
2833 2845          nfs4_ntov_map[27].sv_getit = rfs4_fattr4_maxfilesize;
2834 2846          nfs4_ntov_map[28].sv_getit = rfs4_fattr4_maxlink;
2835 2847          nfs4_ntov_map[29].sv_getit = rfs4_fattr4_maxname;
2836 2848          nfs4_ntov_map[30].sv_getit = rfs4_fattr4_maxread;
2837 2849          nfs4_ntov_map[31].sv_getit = rfs4_fattr4_maxwrite;
2838 2850          nfs4_ntov_map[32].sv_getit = rfs4_fattr4_mimetype;
2839 2851          nfs4_ntov_map[33].sv_getit = rfs4_fattr4_mode;
2840 2852          nfs4_ntov_map[34].sv_getit = rfs4_fattr4_no_trunc;
2841 2853          nfs4_ntov_map[35].sv_getit = rfs4_fattr4_numlinks;
2842 2854          nfs4_ntov_map[36].sv_getit = rfs4_fattr4_owner;
2843 2855          nfs4_ntov_map[37].sv_getit = rfs4_fattr4_owner_group;
2844 2856          nfs4_ntov_map[38].sv_getit = rfs4_fattr4_quota_avail_hard;
2845 2857          nfs4_ntov_map[39].sv_getit = rfs4_fattr4_quota_avail_soft;
2846 2858          nfs4_ntov_map[40].sv_getit = rfs4_fattr4_quota_used;
2847 2859          nfs4_ntov_map[41].sv_getit = rfs4_fattr4_rawdev;
2848 2860          nfs4_ntov_map[42].sv_getit = rfs4_fattr4_space_avail;
2849 2861          nfs4_ntov_map[43].sv_getit = rfs4_fattr4_space_free;
2850 2862          nfs4_ntov_map[44].sv_getit = rfs4_fattr4_space_total;
2851 2863          nfs4_ntov_map[45].sv_getit = rfs4_fattr4_space_used;
2852 2864          nfs4_ntov_map[46].sv_getit = rfs4_fattr4_system;
2853 2865          nfs4_ntov_map[47].sv_getit = rfs4_fattr4_time_access;
2854 2866          nfs4_ntov_map[48].sv_getit = rfs4_fattr4_time_access_set;
2855 2867          nfs4_ntov_map[49].sv_getit = rfs4_fattr4_time_backup;
2856 2868          nfs4_ntov_map[50].sv_getit = rfs4_fattr4_time_create;
2857 2869          nfs4_ntov_map[51].sv_getit = rfs4_fattr4_time_delta;
2858 2870          nfs4_ntov_map[52].sv_getit = rfs4_fattr4_time_metadata;
2859 2871          nfs4_ntov_map[53].sv_getit = rfs4_fattr4_time_modify;
2860 2872          nfs4_ntov_map[54].sv_getit = rfs4_fattr4_time_modify_set;
2861 2873          nfs4_ntov_map[55].sv_getit = rfs4_fattr4_mounted_on_fileid;
2862 2874  }
  
    | 
      ↓ open down ↓ | 
    1469 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX