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