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