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, TRUE); 891 vs_acet_destroy(&vs_native); 892 } else { 893 error = vs_aent_to_ace4(&vs_native, &vs_ace4, 894 vp->v_type == VDIR, TRUE); 895 vs_aent_destroy(&vs_native); 896 } 897 if (error != 0) 898 break; 899 900 if (cmd == NFS4ATTR_GETIT) { 901 na->acl.fattr4_acl_len = vs_ace4.vsa_aclcnt; 902 /* see case NFS4ATTR_FREEIT for this being freed */ 903 na->acl.fattr4_acl_val = vs_ace4.vsa_aclentp; 904 } else { 905 if (na->acl.fattr4_acl_len != vs_ace4.vsa_aclcnt) 906 error = -1; /* no match */ 907 else if (ln_ace4_cmp(na->acl.fattr4_acl_val, 908 vs_ace4.vsa_aclentp, 909 vs_ace4.vsa_aclcnt) != 0) 910 error = -1; /* no match */ 911 } 912 913 break; 914 915 case NFS4ATTR_SETIT: 916 if (sarg->rdattr_error && (vp == NULL)) { 917 return (-1); 918 } 919 ASSERT(vp != NULL); 920 921 /* prepare vs_ace4 from fattr4 data */ 922 bzero(&vs_ace4, sizeof (vs_ace4)); 923 vs_ace4.vsa_mask = VSA_ACE | VSA_ACECNT; 924 vs_ace4.vsa_aclcnt = na->acl.fattr4_acl_len; 925 vs_ace4.vsa_aclentp = na->acl.fattr4_acl_val; 926 927 /* make sure we have correct owner/group */ 928 if ((vap->va_mask & (AT_UID | AT_GID)) != 929 (AT_UID | AT_GID)) { 930 vap = &va; 931 vap->va_mask = AT_UID | AT_GID; 932 status = rfs4_vop_getattr(vp, 933 vap, 0, sarg->cs->cr); 934 if (status != NFS4_OK) 935 return (geterrno4(status)); 936 } 937 938 /* see which ACLs the fs supports */ 939 error = VOP_PATHCONF(vp, _PC_ACL_ENABLED, &whichacl, 940 sarg->cs->cr); 941 if (error != 0) { 942 /* 943 * If we got an error, then the filesystem 944 * likely does not understand the _PC_ACL_ENABLED 945 * pathconf. In this case, we fall back to trying 946 * POSIX-draft (aka UFS-style) ACLs, since that's 947 * the behavior used by earlier version of NFS. 948 */ 949 error = 0; 950 whichacl = _ACL_ACLENT_ENABLED; 951 } 952 953 if (!(whichacl & (_ACL_ACLENT_ENABLED | _ACL_ACE_ENABLED))) { 954 /* 955 * If the file system supports neither ACE nor 956 * ACLENT ACLs we will fall back to UFS-style ACLs 957 * like we did above if there was an error upon 958 * calling VOP_PATHCONF. 959 * 960 * ACE and ACLENT type ACLs are the only interfaces 961 * supported thus far. If any other bits are set on 962 * 'whichacl' upon return from VOP_PATHCONF, we will 963 * ignore them. 964 */ 965 whichacl = _ACL_ACLENT_ENABLED; 966 } 967 968 if (whichacl & _ACL_ACE_ENABLED) { 969 error = vs_ace4_to_acet(&vs_ace4, &vs_native, 970 vap->va_uid, vap->va_gid, TRUE, FALSE); 971 if (error != 0) 972 break; 973 (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL); 974 error = VOP_SETSECATTR(vp, &vs_native, 975 0, sarg->cs->cr); 976 VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL); 977 vs_acet_destroy(&vs_native); 978 } else if (whichacl & _ACL_ACLENT_ENABLED) { 979 error = vs_ace4_to_aent(&vs_ace4, &vs_native, 980 vap->va_uid, vap->va_gid, vp->v_type == VDIR, TRUE, 981 FALSE); 982 if (error != 0) 983 break; 984 (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL); 985 error = VOP_SETSECATTR(vp, &vs_native, 986 0, sarg->cs->cr); 987 VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL); 988 vs_aent_destroy(&vs_native); 989 } 990 break; 991 992 case NFS4ATTR_FREEIT: 993 if (sarg->op == NFS4ATTR_GETIT) { 994 vs_ace4.vsa_mask = VSA_ACE | VSA_ACECNT; 995 vs_ace4.vsa_aclcnt = na->acl.fattr4_acl_len; 996 vs_ace4.vsa_aclentp = na->acl.fattr4_acl_val; 997 vs_ace4_destroy(&vs_ace4); 998 } 999 break; 1000 } 1001 1002 return (error); 1003 } 1004 1005 /* ARGSUSED */ 1006 static int 1007 rfs4_fattr4_aclsupport(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1008 union nfs4_attr_u *na) 1009 { 1010 int error = 0; 1011 1012 if (RFS4_MANDATTR_ONLY) 1013 return (ENOTSUP); 1014 1015 switch (cmd) { 1016 case NFS4ATTR_SUPPORTED: 1017 if (sarg->op == NFS4ATTR_SETIT) 1018 error = EINVAL; 1019 break; /* supported */ 1020 case NFS4ATTR_GETIT: 1021 na->aclsupport = ACL4_SUPPORT_ALLOW_ACL | 1022 ACL4_SUPPORT_DENY_ACL; 1023 break; 1024 case NFS4ATTR_SETIT: 1025 error = EINVAL; 1026 break; 1027 case NFS4ATTR_VERIT: 1028 if (na->aclsupport != (ACL4_SUPPORT_ALLOW_ACL | 1029 ACL4_SUPPORT_DENY_ACL)) 1030 error = -1; /* no match */ 1031 break; 1032 } 1033 1034 return (error); 1035 } 1036 1037 /* ARGSUSED */ 1038 static int 1039 rfs4_fattr4_archive(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1040 union nfs4_attr_u *na) 1041 { 1042 return (ENOTSUP); 1043 } 1044 1045 /* ARGSUSED */ 1046 static int 1047 rfs4_fattr4_cansettime(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1048 union nfs4_attr_u *na) 1049 { 1050 int error = 0; 1051 1052 if (RFS4_MANDATTR_ONLY) 1053 return (ENOTSUP); 1054 1055 switch (cmd) { 1056 case NFS4ATTR_SUPPORTED: 1057 if (sarg->op == NFS4ATTR_SETIT) 1058 error = EINVAL; 1059 break; /* this attr is supported */ 1060 case NFS4ATTR_GETIT: 1061 na->cansettime = TRUE; 1062 break; 1063 case NFS4ATTR_SETIT: 1064 /* 1065 * read-only attr 1066 */ 1067 error = EINVAL; 1068 break; 1069 case NFS4ATTR_VERIT: 1070 if (!na->cansettime) 1071 error = -1; /* no match */ 1072 break; 1073 case NFS4ATTR_FREEIT: 1074 break; 1075 } 1076 return (error); 1077 } 1078 1079 /* 1080 * XXX - need VOP extension to ask file system (e.g. pcfs) if it supports 1081 * case insenstive. 1082 */ 1083 /* ARGSUSED */ 1084 static int 1085 rfs4_fattr4_case_insensitive(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1086 union nfs4_attr_u *na) 1087 { 1088 int error = 0; 1089 1090 if (RFS4_MANDATTR_ONLY) 1091 return (ENOTSUP); 1092 1093 switch (cmd) { 1094 case NFS4ATTR_SUPPORTED: 1095 if (sarg->op == NFS4ATTR_SETIT) 1096 error = EINVAL; 1097 break; /* this attr is supported */ 1098 case NFS4ATTR_GETIT: 1099 na->case_insensitive = FALSE; 1100 break; 1101 case NFS4ATTR_SETIT: 1102 /* 1103 * read-only attr 1104 */ 1105 error = EINVAL; 1106 break; 1107 case NFS4ATTR_VERIT: 1108 if (!na->case_insensitive) 1109 error = -1; /* no match */ 1110 break; 1111 case NFS4ATTR_FREEIT: 1112 break; 1113 } 1114 return (error); 1115 } 1116 1117 /* ARGSUSED */ 1118 static int 1119 rfs4_fattr4_case_preserving(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1120 union nfs4_attr_u *na) 1121 { 1122 int error = 0; 1123 1124 if (RFS4_MANDATTR_ONLY) 1125 return (ENOTSUP); 1126 1127 switch (cmd) { 1128 case NFS4ATTR_SUPPORTED: 1129 if (sarg->op == NFS4ATTR_SETIT) 1130 error = EINVAL; 1131 break; /* this attr is supported */ 1132 case NFS4ATTR_GETIT: 1133 na->case_preserving = TRUE; 1134 break; 1135 case NFS4ATTR_SETIT: 1136 /* 1137 * read-only attr 1138 */ 1139 error = EINVAL; 1140 break; 1141 case NFS4ATTR_VERIT: 1142 if (!na->case_preserving) 1143 error = -1; /* no match */ 1144 break; 1145 case NFS4ATTR_FREEIT: 1146 break; 1147 } 1148 return (error); 1149 } 1150 1151 /* fattr4_chown_restricted should reall be fattr4_chown_allowed */ 1152 /* ARGSUSED */ 1153 static int 1154 rfs4_fattr4_chown_restricted(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1155 union nfs4_attr_u *na) 1156 { 1157 int error = 0; 1158 ulong_t val; 1159 1160 if (RFS4_MANDATTR_ONLY) 1161 return (ENOTSUP); 1162 1163 switch (cmd) { 1164 case NFS4ATTR_SUPPORTED: 1165 if (sarg->op == NFS4ATTR_SETIT) 1166 error = EINVAL; 1167 break; /* this attr is supported */ 1168 case NFS4ATTR_GETIT: 1169 if (sarg->rdattr_error && (sarg->cs->vp == NULL)) { 1170 error = -1; /* may be okay if rdattr_error */ 1171 break; 1172 } 1173 ASSERT(sarg->cs->vp != NULL); 1174 error = VOP_PATHCONF(sarg->cs->vp, 1175 _PC_CHOWN_RESTRICTED, &val, sarg->cs->cr); 1176 if (error) 1177 break; 1178 1179 na->chown_restricted = (val == 1); 1180 break; 1181 case NFS4ATTR_SETIT: 1182 /* 1183 * read-only attr 1184 */ 1185 error = EINVAL; 1186 break; 1187 case NFS4ATTR_VERIT: 1188 ASSERT(sarg->cs->vp != NULL); 1189 error = VOP_PATHCONF(sarg->cs->vp, 1190 _PC_CHOWN_RESTRICTED, &val, sarg->cs->cr); 1191 if (error) 1192 break; 1193 if (na->chown_restricted != (val == 1)) 1194 error = -1; /* no match */ 1195 break; 1196 case NFS4ATTR_FREEIT: 1197 break; 1198 } 1199 return (error); 1200 } 1201 1202 /* ARGSUSED */ 1203 static int 1204 rfs4_fattr4_fileid(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1205 union nfs4_attr_u *na) 1206 { 1207 int error = 0; 1208 1209 if (RFS4_MANDATTR_ONLY) 1210 return (ENOTSUP); 1211 1212 switch (cmd) { 1213 case NFS4ATTR_SUPPORTED: 1214 if (sarg->op == NFS4ATTR_SETIT) 1215 error = EINVAL; 1216 break; /* this attr is supported */ 1217 case NFS4ATTR_GETIT: 1218 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_NODEID)) { 1219 error = -1; /* may be okay if rdattr_error */ 1220 break; 1221 } 1222 ASSERT(sarg->vap->va_mask & AT_NODEID); 1223 na->fileid = sarg->vap->va_nodeid; 1224 break; 1225 case NFS4ATTR_SETIT: 1226 /* 1227 * read-only attr 1228 */ 1229 error = EINVAL; 1230 break; 1231 case NFS4ATTR_VERIT: 1232 ASSERT(sarg->vap->va_mask & AT_NODEID); 1233 if (sarg->vap->va_nodeid != na->fileid) 1234 error = -1; /* no match */ 1235 break; 1236 case NFS4ATTR_FREEIT: 1237 break; 1238 } 1239 return (error); 1240 } 1241 1242 /* ARGSUSED */ 1243 static int 1244 rfs4_get_mntdfileid(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg) 1245 { 1246 int error = 0; 1247 vattr_t *vap, va; 1248 vnode_t *stubvp = NULL, *vp; 1249 1250 vp = sarg->cs->vp; 1251 sarg->mntdfid_set = FALSE; 1252 1253 /* VROOT object, must untraverse */ 1254 if (vp->v_flag & VROOT) { 1255 1256 /* extra hold for vp since untraverse might rele */ 1257 VN_HOLD(vp); 1258 stubvp = untraverse(vp); 1259 1260 /* 1261 * If vp/stubvp are same, we must be at system 1262 * root because untraverse returned same vp 1263 * for a VROOT object. sarg->vap was setup 1264 * before we got here, so there's no need to do 1265 * another getattr -- just use the one in sarg. 1266 */ 1267 if (VN_CMP(vp, stubvp)) { 1268 ASSERT(VN_CMP(vp, rootdir)); 1269 vap = sarg->vap; 1270 } else { 1271 va.va_mask = AT_NODEID; 1272 vap = &va; 1273 error = rfs4_vop_getattr(stubvp, vap, 0, sarg->cs->cr); 1274 } 1275 1276 /* 1277 * Done with stub, time to rele. If vp and stubvp 1278 * were the same, then we need to rele either vp or 1279 * stubvp. If they weren't the same, then untraverse() 1280 * already took case of the extra hold on vp, and only 1281 * the stub needs to be rele'd. Both cases are handled 1282 * by unconditionally rele'ing the stub. 1283 */ 1284 VN_RELE(stubvp); 1285 } else 1286 vap = sarg->vap; 1287 1288 /* 1289 * At this point, vap should contain "correct" AT_NODEID -- 1290 * (for V_ROOT case, nodeid of stub, for non-VROOT case, 1291 * nodeid of vp). If error or AT_NODEID not available, then 1292 * make the obligatory (yet mysterious) rdattr_error 1293 * check that is so common in the attr code. 1294 */ 1295 if (!error && (vap->va_mask & AT_NODEID)) { 1296 sarg->mounted_on_fileid = vap->va_nodeid; 1297 sarg->mntdfid_set = TRUE; 1298 } else if (sarg->rdattr_error) 1299 error = -1; 1300 1301 /* 1302 * error describes these cases: 1303 * 0 : success 1304 * -1: failure due to previous attr processing error (rddir only). 1305 * * : new attr failure (if rddir, caller will set rdattr_error) 1306 */ 1307 return (error); 1308 } 1309 1310 /* ARGSUSED */ 1311 static int 1312 rfs4_fattr4_mounted_on_fileid(nfs4_attr_cmd_t cmd, 1313 struct nfs4_svgetit_arg *sarg, union nfs4_attr_u *na) 1314 { 1315 int error = 0; 1316 1317 if (RFS4_MANDATTR_ONLY) 1318 return (ENOTSUP); 1319 1320 switch (cmd) { 1321 case NFS4ATTR_SUPPORTED: 1322 if (sarg->op == NFS4ATTR_SETIT) 1323 error = EINVAL; 1324 break; /* this attr is supported */ 1325 case NFS4ATTR_GETIT: 1326 case NFS4ATTR_VERIT: 1327 if (! sarg->mntdfid_set) 1328 error = rfs4_get_mntdfileid(cmd, sarg); 1329 1330 if (! error && sarg->mntdfid_set) { 1331 if (cmd == NFS4ATTR_GETIT) 1332 na->mounted_on_fileid = sarg->mounted_on_fileid; 1333 else 1334 if (na->mounted_on_fileid != 1335 sarg->mounted_on_fileid) 1336 error = -1; 1337 } 1338 break; 1339 case NFS4ATTR_SETIT: 1340 /* read-only attr */ 1341 error = EINVAL; 1342 break; 1343 case NFS4ATTR_FREEIT: 1344 break; 1345 } 1346 return (error); 1347 } 1348 1349 /* ARGSUSED */ 1350 static int 1351 rfs4_fattr4_files_avail(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1352 union nfs4_attr_u *na) 1353 { 1354 int error = 0; 1355 1356 if (RFS4_MANDATTR_ONLY) 1357 return (ENOTSUP); 1358 1359 switch (cmd) { 1360 case NFS4ATTR_SUPPORTED: 1361 if (sarg->op == NFS4ATTR_SETIT) 1362 error = EINVAL; 1363 break; /* this attr is supported */ 1364 case NFS4ATTR_GETIT: 1365 if (sarg->rdattr_error && (sarg->sbp == NULL)) { 1366 error = -1; /* may be okay if rdattr_error */ 1367 break; 1368 } 1369 ASSERT(sarg->sbp != NULL); 1370 na->files_avail = sarg->sbp->f_favail; 1371 break; 1372 case NFS4ATTR_SETIT: 1373 /* 1374 * read-only attr 1375 */ 1376 error = EINVAL; 1377 break; 1378 case NFS4ATTR_VERIT: 1379 ASSERT(sarg->sbp != NULL); 1380 if (sarg->sbp->f_favail != na->files_avail) 1381 error = -1; /* no match */ 1382 break; 1383 case NFS4ATTR_FREEIT: 1384 break; 1385 } 1386 return (error); 1387 } 1388 1389 /* ARGSUSED */ 1390 static int 1391 rfs4_fattr4_files_free(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1392 union nfs4_attr_u *na) 1393 { 1394 int error = 0; 1395 1396 if (RFS4_MANDATTR_ONLY) 1397 return (ENOTSUP); 1398 1399 switch (cmd) { 1400 case NFS4ATTR_SUPPORTED: 1401 if (sarg->op == NFS4ATTR_SETIT) 1402 error = EINVAL; 1403 break; /* this attr is supported */ 1404 case NFS4ATTR_GETIT: 1405 if (sarg->rdattr_error && (sarg->sbp == NULL)) { 1406 error = -1; /* may be okay if rdattr_error */ 1407 break; 1408 } 1409 ASSERT(sarg->sbp != NULL); 1410 na->files_free = sarg->sbp->f_ffree; 1411 break; 1412 case NFS4ATTR_SETIT: 1413 /* 1414 * read-only attr 1415 */ 1416 error = EINVAL; 1417 break; 1418 case NFS4ATTR_VERIT: 1419 ASSERT(sarg->sbp != NULL); 1420 if (sarg->sbp->f_ffree != na->files_free) 1421 error = -1; /* no match */ 1422 break; 1423 case NFS4ATTR_FREEIT: 1424 break; 1425 } 1426 return (error); 1427 } 1428 1429 /* ARGSUSED */ 1430 static int 1431 rfs4_fattr4_files_total(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1432 union nfs4_attr_u *na) 1433 { 1434 int error = 0; 1435 1436 if (RFS4_MANDATTR_ONLY) 1437 return (ENOTSUP); 1438 1439 switch (cmd) { 1440 case NFS4ATTR_SUPPORTED: 1441 if (sarg->op == NFS4ATTR_SETIT) 1442 error = EINVAL; 1443 break; /* this attr is supported */ 1444 case NFS4ATTR_GETIT: 1445 if (sarg->rdattr_error && (sarg->sbp == NULL)) { 1446 error = -1; /* may be okay if rdattr_error */ 1447 break; 1448 } 1449 ASSERT(sarg->sbp != NULL); 1450 na->files_total = sarg->sbp->f_files; 1451 break; 1452 case NFS4ATTR_SETIT: 1453 /* 1454 * read-only attr 1455 */ 1456 error = EINVAL; 1457 break; 1458 case NFS4ATTR_VERIT: 1459 ASSERT(sarg->sbp != NULL); 1460 if (sarg->sbp->f_files != na->files_total) 1461 error = -1; /* no match */ 1462 break; 1463 case NFS4ATTR_FREEIT: 1464 break; 1465 } 1466 return (error); 1467 } 1468 1469 /* ARGSUSED */ 1470 static int 1471 rfs4_fattr4_fs_locations(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1472 union nfs4_attr_u *na) 1473 { 1474 return (ENOTSUP); 1475 } 1476 1477 /* ARGSUSED */ 1478 static int 1479 rfs4_fattr4_hidden(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1480 union nfs4_attr_u *na) 1481 { 1482 return (ENOTSUP); 1483 } 1484 1485 /* ARGSUSED */ 1486 static int 1487 rfs4_fattr4_homogeneous(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1488 union nfs4_attr_u *na) 1489 { 1490 int error = 0; 1491 1492 if (RFS4_MANDATTR_ONLY) 1493 return (ENOTSUP); 1494 1495 switch (cmd) { 1496 case NFS4ATTR_SUPPORTED: 1497 if (sarg->op == NFS4ATTR_SETIT) 1498 error = EINVAL; 1499 break; /* this attr is supported */ 1500 case NFS4ATTR_GETIT: 1501 na->homogeneous = TRUE; /* XXX - need a VOP extension */ 1502 break; 1503 case NFS4ATTR_SETIT: 1504 /* 1505 * read-only attr 1506 */ 1507 error = EINVAL; 1508 break; 1509 case NFS4ATTR_VERIT: 1510 if (!na->homogeneous) 1511 error = -1; /* no match */ 1512 break; 1513 case NFS4ATTR_FREEIT: 1514 break; 1515 } 1516 return (error); 1517 } 1518 1519 /* ARGSUSED */ 1520 static int 1521 rfs4_fattr4_maxfilesize(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1522 union nfs4_attr_u *na) 1523 { 1524 int error = 0; 1525 ulong_t val; 1526 fattr4_maxfilesize maxfilesize; 1527 1528 if (RFS4_MANDATTR_ONLY) 1529 return (ENOTSUP); 1530 1531 switch (cmd) { 1532 case NFS4ATTR_SUPPORTED: 1533 if (sarg->op == NFS4ATTR_SETIT) 1534 error = EINVAL; 1535 break; /* this attr is supported */ 1536 case NFS4ATTR_GETIT: 1537 if (sarg->rdattr_error && (sarg->cs->vp == NULL)) { 1538 error = -1; /* may be okay if rdattr_error */ 1539 break; 1540 } 1541 ASSERT(sarg->cs->vp != NULL); 1542 error = VOP_PATHCONF(sarg->cs->vp, _PC_FILESIZEBITS, &val, 1543 sarg->cs->cr); 1544 if (error) 1545 break; 1546 if (val >= (sizeof (uint64_t) * 8)) 1547 na->maxfilesize = UINT64_MAX; 1548 else 1549 na->maxfilesize = ((1LL << val) - 1); 1550 break; 1551 case NFS4ATTR_SETIT: 1552 /* 1553 * read-only attr 1554 */ 1555 error = EINVAL; 1556 break; 1557 case NFS4ATTR_VERIT: 1558 ASSERT(sarg->cs->vp != NULL); 1559 error = VOP_PATHCONF(sarg->cs->vp, _PC_FILESIZEBITS, &val, 1560 sarg->cs->cr); 1561 if (error) 1562 break; 1563 if (val >= (sizeof (uint64_t) * 8)) 1564 maxfilesize = UINT64_MAX; 1565 else 1566 maxfilesize = ((1LL << val) - 1); 1567 if (na->maxfilesize != maxfilesize) 1568 error = -1; /* no match */ 1569 break; 1570 case NFS4ATTR_FREEIT: 1571 break; 1572 } 1573 return (error); 1574 } 1575 1576 /* ARGSUSED */ 1577 static int 1578 rfs4_fattr4_maxlink(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1579 union nfs4_attr_u *na) 1580 { 1581 int error = 0; 1582 ulong_t val; 1583 1584 if (RFS4_MANDATTR_ONLY) 1585 return (ENOTSUP); 1586 1587 switch (cmd) { 1588 case NFS4ATTR_SUPPORTED: 1589 if (sarg->op == NFS4ATTR_SETIT) 1590 error = EINVAL; 1591 break; /* this attr is supported */ 1592 case NFS4ATTR_GETIT: 1593 if (sarg->rdattr_error && (sarg->cs->vp == NULL)) { 1594 error = -1; /* may be okay if rdattr_error */ 1595 break; 1596 } 1597 ASSERT(sarg->cs->vp != NULL); 1598 error = VOP_PATHCONF(sarg->cs->vp, _PC_LINK_MAX, &val, 1599 sarg->cs->cr); 1600 if (error == 0) { 1601 na->maxlink = val; 1602 } 1603 break; 1604 case NFS4ATTR_SETIT: 1605 /* 1606 * read-only attr 1607 */ 1608 error = EINVAL; 1609 break; 1610 case NFS4ATTR_VERIT: 1611 ASSERT(sarg->cs->vp != NULL); 1612 error = VOP_PATHCONF(sarg->cs->vp, _PC_LINK_MAX, &val, 1613 sarg->cs->cr); 1614 if (!error && (na->maxlink != val)) 1615 error = -1; /* no match */ 1616 break; 1617 case NFS4ATTR_FREEIT: 1618 break; 1619 } 1620 return (error); 1621 } 1622 1623 /* ARGSUSED */ 1624 static int 1625 rfs4_fattr4_maxname(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1626 union nfs4_attr_u *na) 1627 { 1628 int error = 0; 1629 ulong_t val; 1630 1631 if (RFS4_MANDATTR_ONLY) 1632 return (ENOTSUP); 1633 1634 switch (cmd) { 1635 case NFS4ATTR_SUPPORTED: 1636 if (sarg->op == NFS4ATTR_SETIT) 1637 error = EINVAL; 1638 break; /* this attr is supported */ 1639 case NFS4ATTR_GETIT: 1640 if (sarg->rdattr_error && (sarg->cs->vp == NULL)) { 1641 error = -1; /* may be okay if rdattr_error */ 1642 break; 1643 } 1644 ASSERT(sarg->cs->vp != NULL); 1645 error = VOP_PATHCONF(sarg->cs->vp, _PC_NAME_MAX, &val, 1646 sarg->cs->cr); 1647 if (error == 0) { 1648 na->maxname = val; 1649 } 1650 break; 1651 case NFS4ATTR_SETIT: 1652 /* 1653 * read-only attr 1654 */ 1655 error = EINVAL; 1656 break; 1657 case NFS4ATTR_VERIT: 1658 ASSERT(sarg->cs->vp != NULL); 1659 error = VOP_PATHCONF(sarg->cs->vp, _PC_NAME_MAX, &val, 1660 sarg->cs->cr); 1661 if (!error && (na->maxname != val)) 1662 error = -1; /* no match */ 1663 break; 1664 case NFS4ATTR_FREEIT: 1665 break; 1666 } 1667 return (error); 1668 } 1669 1670 /* ARGSUSED */ 1671 static int 1672 rfs4_fattr4_maxread(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1673 union nfs4_attr_u *na) 1674 { 1675 int error = 0; 1676 1677 if (RFS4_MANDATTR_ONLY) 1678 return (ENOTSUP); 1679 1680 switch (cmd) { 1681 case NFS4ATTR_SUPPORTED: 1682 if (sarg->op == NFS4ATTR_SETIT) 1683 error = EINVAL; 1684 break; /* this attr is supported */ 1685 case NFS4ATTR_GETIT: 1686 na->maxread = rfs4_tsize(sarg->cs->req); 1687 break; 1688 case NFS4ATTR_SETIT: 1689 /* 1690 * read-only attr 1691 */ 1692 error = EINVAL; 1693 break; 1694 case NFS4ATTR_VERIT: 1695 if (na->maxread != rfs4_tsize(sarg->cs->req)) 1696 error = -1; /* no match */ 1697 break; 1698 case NFS4ATTR_FREEIT: 1699 break; 1700 } 1701 return (error); 1702 } 1703 1704 /* ARGSUSED */ 1705 static int 1706 rfs4_fattr4_maxwrite(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1707 union nfs4_attr_u *na) 1708 { 1709 int error = 0; 1710 1711 if (RFS4_MANDATTR_ONLY) 1712 return (ENOTSUP); 1713 1714 switch (cmd) { 1715 case NFS4ATTR_SUPPORTED: 1716 if (sarg->op == NFS4ATTR_SETIT) 1717 error = EINVAL; 1718 break; /* this attr is supported */ 1719 case NFS4ATTR_GETIT: 1720 na->maxwrite = rfs4_tsize(sarg->cs->req); 1721 break; 1722 case NFS4ATTR_SETIT: 1723 /* 1724 * read-only attr 1725 */ 1726 error = EINVAL; 1727 break; 1728 case NFS4ATTR_VERIT: 1729 if (na->maxwrite != rfs4_tsize(sarg->cs->req)) 1730 error = -1; /* no match */ 1731 break; 1732 case NFS4ATTR_FREEIT: 1733 break; 1734 } 1735 return (error); 1736 } 1737 1738 /* ARGSUSED */ 1739 static int 1740 rfs4_fattr4_mimetype(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1741 union nfs4_attr_u *na) 1742 { 1743 return (ENOTSUP); 1744 } 1745 1746 /* ARGSUSED */ 1747 static int 1748 rfs4_fattr4_mode(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1749 union nfs4_attr_u *na) 1750 { 1751 int error = 0; 1752 1753 if (RFS4_MANDATTR_ONLY) 1754 return (ENOTSUP); 1755 1756 switch (cmd) { 1757 case NFS4ATTR_SUPPORTED: 1758 break; /* this attr is supported */ 1759 case NFS4ATTR_GETIT: 1760 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_MODE)) { 1761 error = -1; /* may be okay if rdattr_error */ 1762 break; 1763 } 1764 ASSERT(sarg->vap->va_mask & AT_MODE); 1765 na->mode = sarg->vap->va_mode; 1766 break; 1767 case NFS4ATTR_SETIT: 1768 ASSERT(sarg->vap->va_mask & AT_MODE); 1769 sarg->vap->va_mode = na->mode; 1770 /* 1771 * If the filesystem is exported with nosuid, then mask off 1772 * the setuid and setgid bits. 1773 */ 1774 if (sarg->cs->vp->v_type == VREG && 1775 (sarg->cs->exi->exi_export.ex_flags & EX_NOSUID)) 1776 sarg->vap->va_mode &= ~(VSUID | VSGID); 1777 break; 1778 case NFS4ATTR_VERIT: 1779 ASSERT(sarg->vap->va_mask & AT_MODE); 1780 if (sarg->vap->va_mode != na->mode) 1781 error = -1; /* no match */ 1782 break; 1783 case NFS4ATTR_FREEIT: 1784 break; 1785 } 1786 return (error); 1787 } 1788 1789 /* ARGSUSED */ 1790 static int 1791 rfs4_fattr4_no_trunc(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1792 union nfs4_attr_u *na) 1793 { 1794 int error = 0; 1795 1796 if (RFS4_MANDATTR_ONLY) 1797 return (ENOTSUP); 1798 1799 switch (cmd) { 1800 case NFS4ATTR_SUPPORTED: 1801 if (sarg->op == NFS4ATTR_SETIT) 1802 error = EINVAL; 1803 break; /* this attr is supported */ 1804 case NFS4ATTR_GETIT: 1805 na->no_trunc = TRUE; 1806 break; 1807 case NFS4ATTR_SETIT: 1808 /* 1809 * read-only attr 1810 */ 1811 error = EINVAL; 1812 break; 1813 case NFS4ATTR_VERIT: 1814 if (!na->no_trunc) 1815 error = -1; /* no match */ 1816 break; 1817 case NFS4ATTR_FREEIT: 1818 break; 1819 } 1820 return (error); 1821 } 1822 1823 /* ARGSUSED */ 1824 static int 1825 rfs4_fattr4_numlinks(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1826 union nfs4_attr_u *na) 1827 { 1828 int error = 0; 1829 1830 if (RFS4_MANDATTR_ONLY) 1831 return (ENOTSUP); 1832 1833 switch (cmd) { 1834 case NFS4ATTR_SUPPORTED: 1835 if (sarg->op == NFS4ATTR_SETIT) 1836 error = EINVAL; 1837 break; /* this attr is supported */ 1838 case NFS4ATTR_GETIT: 1839 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_NLINK)) { 1840 error = -1; /* may be okay if rdattr_error */ 1841 break; 1842 } 1843 ASSERT(sarg->vap->va_mask & AT_NLINK); 1844 na->numlinks = sarg->vap->va_nlink; 1845 break; 1846 case NFS4ATTR_SETIT: 1847 /* 1848 * read-only attr 1849 */ 1850 error = EINVAL; 1851 break; 1852 case NFS4ATTR_VERIT: 1853 ASSERT(sarg->vap->va_mask & AT_NLINK); 1854 if (sarg->vap->va_nlink != na->numlinks) 1855 error = -1; /* no match */ 1856 break; 1857 case NFS4ATTR_FREEIT: 1858 break; 1859 } 1860 return (error); 1861 } 1862 1863 /* ARGSUSED */ 1864 static int 1865 rfs4_fattr4_owner(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1866 union nfs4_attr_u *na) 1867 { 1868 int error = 0; 1869 uid_t uid; 1870 1871 if (RFS4_MANDATTR_ONLY) 1872 return (ENOTSUP); 1873 1874 switch (cmd) { 1875 case NFS4ATTR_SUPPORTED: 1876 break; /* this attr is supported */ 1877 case NFS4ATTR_GETIT: 1878 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_UID)) { 1879 error = -1; /* may be okay if rdattr_error */ 1880 break; 1881 } 1882 ASSERT(sarg->vap->va_mask & AT_UID); 1883 1884 /* 1885 * There are well defined polices for what happens on server- 1886 * side GETATTR when uid to attribute string conversion cannot 1887 * occur. Please refer to nfs4_idmap.c for details. 1888 */ 1889 error = nfs_idmap_uid_str(sarg->vap->va_uid, &na->owner, TRUE); 1890 switch (error) { 1891 case ECONNREFUSED: 1892 error = NFS4ERR_DELAY; 1893 break; 1894 default: 1895 break; 1896 } 1897 break; 1898 1899 case NFS4ATTR_SETIT: 1900 ASSERT(sarg->vap->va_mask & AT_UID); 1901 1902 /* 1903 * There are well defined policies for what happens on server- 1904 * side SETATTR of 'owner' when a "user@domain" mapping cannot 1905 * occur. Please refer to nfs4_idmap.c for details. 1906 * 1907 * Any other errors, such as the mapping not being found by 1908 * nfsmapid(1m), and interrupted clnt_call, etc, will result 1909 * in NFS4ERR_BADOWNER. 1910 * 1911 * XXX need to return consistent errors, perhaps all 1912 * server side attribute routines should return NFS4ERR*. 1913 */ 1914 error = nfs_idmap_str_uid(&na->owner, &sarg->vap->va_uid, TRUE); 1915 switch (error) { 1916 case NFS4_OK: 1917 case ENOTSUP: 1918 /* 1919 * Ignore warning that we are the 1920 * nfsmapid (can't happen on srv) 1921 */ 1922 error = 0; 1923 MSG_PRT_DEBUG = FALSE; 1924 break; 1925 1926 case ECOMM: 1927 case ECONNREFUSED: 1928 if (!MSG_PRT_DEBUG) { 1929 /* 1930 * printed just once per daemon death, 1931 * inform the user and then stay silent 1932 */ 1933 cmn_err(CE_WARN, "!Unable to contact " 1934 "nfsmapid"); 1935 MSG_PRT_DEBUG = TRUE; 1936 } 1937 error = NFS4ERR_DELAY; 1938 break; 1939 1940 case EINVAL: 1941 error = NFS4ERR_INVAL; 1942 break; 1943 1944 default: 1945 error = NFS4ERR_BADOWNER; 1946 break; 1947 } 1948 break; 1949 1950 case NFS4ATTR_VERIT: 1951 ASSERT(sarg->vap->va_mask & AT_UID); 1952 error = nfs_idmap_str_uid(&na->owner, &uid, TRUE); 1953 /* 1954 * Ignore warning that we are the nfsmapid (can't happen on srv) 1955 */ 1956 if (error == ENOTSUP) 1957 error = 0; 1958 if (error) 1959 error = -1; /* no match */ 1960 else if (sarg->vap->va_uid != uid) 1961 error = -1; /* no match */ 1962 break; 1963 case NFS4ATTR_FREEIT: 1964 if (sarg->op == NFS4ATTR_GETIT) { 1965 if (na->owner.utf8string_val) { 1966 UTF8STRING_FREE(na->owner) 1967 bzero(&na->owner, sizeof (na->owner)); 1968 } 1969 } 1970 break; 1971 } 1972 return (error); 1973 } 1974 1975 /* ARGSUSED */ 1976 static int 1977 rfs4_fattr4_owner_group(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 1978 union nfs4_attr_u *na) 1979 { 1980 int error = 0; 1981 gid_t gid; 1982 1983 if (RFS4_MANDATTR_ONLY) 1984 return (ENOTSUP); 1985 1986 switch (cmd) { 1987 case NFS4ATTR_SUPPORTED: 1988 break; /* this attr is supported */ 1989 case NFS4ATTR_GETIT: 1990 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_GID)) { 1991 error = -1; /* may be okay if rdattr_error */ 1992 break; 1993 } 1994 ASSERT(sarg->vap->va_mask & AT_GID); 1995 1996 /* 1997 * There are well defined polices for what happens on server- 1998 * side GETATTR when gid to attribute string conversion cannot 1999 * occur. Please refer to nfs4_idmap.c for details. 2000 */ 2001 error = nfs_idmap_gid_str(sarg->vap->va_gid, &na->owner_group, 2002 TRUE); 2003 switch (error) { 2004 case ECONNREFUSED: 2005 error = NFS4ERR_DELAY; 2006 break; 2007 default: 2008 break; 2009 } 2010 break; 2011 2012 case NFS4ATTR_SETIT: 2013 ASSERT(sarg->vap->va_mask & AT_GID); 2014 2015 /* 2016 * There are well defined policies for what happens on server- 2017 * side SETATTR of 'owner_group' when a "group@domain" mapping 2018 * cannot occur. Please refer to nfs4_idmap.c for details. 2019 * 2020 * Any other errors, such as the mapping not being found by 2021 * nfsmapid(1m), and interrupted clnt_call, etc, will result 2022 * in NFS4ERR_BADOWNER. 2023 * 2024 * XXX need to return consistent errors, perhaps all 2025 * server side attribute routines should return NFS4ERR*. 2026 */ 2027 error = nfs_idmap_str_gid(&na->owner_group, &sarg->vap->va_gid, 2028 TRUE); 2029 switch (error) { 2030 case NFS4_OK: 2031 case ENOTSUP: 2032 /* 2033 * Ignore warning that we are the 2034 * nfsmapid (can't happen on srv) 2035 */ 2036 error = 0; 2037 MSG_PRT_DEBUG = FALSE; 2038 break; 2039 2040 case ECOMM: 2041 case ECONNREFUSED: 2042 if (!MSG_PRT_DEBUG) { 2043 /* 2044 * printed just once per daemon death, 2045 * inform the user and then stay silent 2046 */ 2047 cmn_err(CE_WARN, "!Unable to contact " 2048 "nfsmapid"); 2049 MSG_PRT_DEBUG = TRUE; 2050 } 2051 error = NFS4ERR_DELAY; 2052 break; 2053 2054 case EINVAL: 2055 error = NFS4ERR_INVAL; 2056 break; 2057 2058 default: 2059 error = NFS4ERR_BADOWNER; 2060 break; 2061 } 2062 break; 2063 2064 case NFS4ATTR_VERIT: 2065 ASSERT(sarg->vap->va_mask & AT_GID); 2066 error = nfs_idmap_str_gid(&na->owner_group, &gid, TRUE); 2067 /* 2068 * Ignore warning that we are the nfsmapid (can't happen on srv) 2069 */ 2070 if (error == ENOTSUP) 2071 error = 0; 2072 if (error) 2073 error = -1; /* no match */ 2074 else if (sarg->vap->va_gid != gid) 2075 error = -1; /* no match */ 2076 break; 2077 case NFS4ATTR_FREEIT: 2078 if (sarg->op == NFS4ATTR_GETIT) { 2079 if (na->owner_group.utf8string_val) { 2080 UTF8STRING_FREE(na->owner_group) 2081 bzero(&na->owner_group, 2082 sizeof (na->owner_group)); 2083 } 2084 } 2085 break; 2086 } 2087 return (error); 2088 } 2089 2090 /* XXX - quota attributes should be supportable on Solaris 2 */ 2091 /* ARGSUSED */ 2092 static int 2093 rfs4_fattr4_quota_avail_hard(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2094 union nfs4_attr_u *na) 2095 { 2096 return (ENOTSUP); 2097 } 2098 2099 /* ARGSUSED */ 2100 static int 2101 rfs4_fattr4_quota_avail_soft(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2102 union nfs4_attr_u *na) 2103 { 2104 return (ENOTSUP); 2105 } 2106 2107 /* ARGSUSED */ 2108 static int 2109 rfs4_fattr4_quota_used(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2110 union nfs4_attr_u *na) 2111 { 2112 return (ENOTSUP); 2113 } 2114 2115 /* ARGSUSED */ 2116 static int 2117 rfs4_fattr4_rawdev(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2118 union nfs4_attr_u *na) 2119 { 2120 int error = 0; 2121 2122 if (RFS4_MANDATTR_ONLY) 2123 return (ENOTSUP); 2124 2125 switch (cmd) { 2126 case NFS4ATTR_SUPPORTED: 2127 if (sarg->op == NFS4ATTR_SETIT) 2128 error = EINVAL; 2129 break; /* this attr is supported */ 2130 case NFS4ATTR_GETIT: 2131 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_RDEV)) { 2132 error = -1; /* may be okay if rdattr_error */ 2133 break; 2134 } 2135 ASSERT(sarg->vap->va_mask & AT_RDEV); 2136 na->rawdev.specdata1 = (uint32)getmajor(sarg->vap->va_rdev); 2137 na->rawdev.specdata2 = (uint32)getminor(sarg->vap->va_rdev); 2138 break; 2139 case NFS4ATTR_SETIT: 2140 /* 2141 * read-only attr 2142 */ 2143 error = EINVAL; 2144 break; 2145 case NFS4ATTR_VERIT: 2146 ASSERT(sarg->vap->va_mask & AT_RDEV); 2147 if ((na->rawdev.specdata1 != 2148 (uint32)getmajor(sarg->vap->va_rdev)) || 2149 (na->rawdev.specdata2 != 2150 (uint32)getminor(sarg->vap->va_rdev))) 2151 error = -1; /* no match */ 2152 break; 2153 case NFS4ATTR_FREEIT: 2154 break; 2155 } 2156 return (error); 2157 } 2158 2159 /* ARGSUSED */ 2160 static int 2161 rfs4_fattr4_space_avail(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2162 union nfs4_attr_u *na) 2163 { 2164 int error = 0; 2165 2166 if (RFS4_MANDATTR_ONLY) 2167 return (ENOTSUP); 2168 2169 switch (cmd) { 2170 case NFS4ATTR_SUPPORTED: 2171 if (sarg->op == NFS4ATTR_SETIT) 2172 error = EINVAL; 2173 break; /* this attr is supported */ 2174 case NFS4ATTR_GETIT: 2175 if (sarg->rdattr_error && (sarg->sbp == NULL)) { 2176 error = -1; /* may be okay if rdattr_error */ 2177 break; 2178 } 2179 ASSERT(sarg->sbp != NULL); 2180 if (sarg->sbp->f_bavail != (fsblkcnt64_t)-1) { 2181 na->space_avail = 2182 (fattr4_space_avail) sarg->sbp->f_frsize * 2183 (fattr4_space_avail) sarg->sbp->f_bavail; 2184 } else { 2185 na->space_avail = 2186 (fattr4_space_avail) sarg->sbp->f_bavail; 2187 } 2188 break; 2189 case NFS4ATTR_SETIT: 2190 /* 2191 * read-only attr 2192 */ 2193 error = EINVAL; 2194 break; 2195 case NFS4ATTR_VERIT: 2196 ASSERT(sarg->sbp != NULL); 2197 if (sarg->sbp->f_bavail != na->space_avail) 2198 error = -1; /* no match */ 2199 break; 2200 case NFS4ATTR_FREEIT: 2201 break; 2202 } 2203 return (error); 2204 } 2205 2206 /* ARGSUSED */ 2207 static int 2208 rfs4_fattr4_space_free(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2209 union nfs4_attr_u *na) 2210 { 2211 int error = 0; 2212 2213 if (RFS4_MANDATTR_ONLY) 2214 return (ENOTSUP); 2215 2216 switch (cmd) { 2217 case NFS4ATTR_SUPPORTED: 2218 if (sarg->op == NFS4ATTR_SETIT) 2219 error = EINVAL; 2220 break; /* this attr is supported */ 2221 case NFS4ATTR_GETIT: 2222 if (sarg->rdattr_error && (sarg->sbp == NULL)) { 2223 error = -1; /* may be okay if rdattr_error */ 2224 break; 2225 } 2226 ASSERT(sarg->sbp != NULL); 2227 if (sarg->sbp->f_bfree != (fsblkcnt64_t)-1) { 2228 na->space_free = 2229 (fattr4_space_free) sarg->sbp->f_frsize * 2230 (fattr4_space_free) sarg->sbp->f_bfree; 2231 } else { 2232 na->space_free = 2233 (fattr4_space_free) sarg->sbp->f_bfree; 2234 } 2235 break; 2236 case NFS4ATTR_SETIT: 2237 /* 2238 * read-only attr 2239 */ 2240 error = EINVAL; 2241 break; 2242 case NFS4ATTR_VERIT: 2243 ASSERT(sarg->sbp != NULL); 2244 if (sarg->sbp->f_bfree != na->space_free) 2245 error = -1; /* no match */ 2246 break; 2247 case NFS4ATTR_FREEIT: 2248 break; 2249 } 2250 return (error); 2251 } 2252 2253 /* ARGSUSED */ 2254 static int 2255 rfs4_fattr4_space_total(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2256 union nfs4_attr_u *na) 2257 { 2258 int error = 0; 2259 2260 if (RFS4_MANDATTR_ONLY) 2261 return (ENOTSUP); 2262 2263 switch (cmd) { 2264 case NFS4ATTR_SUPPORTED: 2265 if (sarg->op == NFS4ATTR_SETIT) 2266 error = EINVAL; 2267 break; /* this attr is supported */ 2268 case NFS4ATTR_GETIT: 2269 if (sarg->rdattr_error_req && (sarg->sbp == NULL)) { 2270 error = -1; /* may be okay if rdattr_error */ 2271 break; 2272 } 2273 ASSERT(sarg->sbp != NULL); 2274 if (sarg->sbp->f_blocks != (fsblkcnt64_t)-1) { 2275 na->space_total = 2276 (fattr4_space_total) sarg->sbp->f_frsize * 2277 (fattr4_space_total) sarg->sbp->f_blocks; 2278 } else { 2279 na->space_total = 2280 (fattr4_space_total) sarg->sbp->f_blocks; 2281 } 2282 break; 2283 case NFS4ATTR_SETIT: 2284 /* 2285 * read-only attr 2286 */ 2287 error = EINVAL; 2288 break; 2289 case NFS4ATTR_VERIT: 2290 ASSERT(sarg->sbp != NULL); 2291 if (sarg->sbp->f_blocks != na->space_total) 2292 error = -1; /* no match */ 2293 break; 2294 case NFS4ATTR_FREEIT: 2295 break; 2296 } 2297 return (error); 2298 } 2299 2300 /* ARGSUSED */ 2301 static int 2302 rfs4_fattr4_space_used(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2303 union nfs4_attr_u *na) 2304 { 2305 int error = 0; 2306 2307 if (RFS4_MANDATTR_ONLY) 2308 return (ENOTSUP); 2309 2310 switch (cmd) { 2311 case NFS4ATTR_SUPPORTED: 2312 if (sarg->op == NFS4ATTR_SETIT) 2313 error = EINVAL; 2314 break; /* this attr is supported */ 2315 case NFS4ATTR_GETIT: 2316 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_NBLOCKS)) { 2317 error = -1; /* may be okay if rdattr_error */ 2318 break; 2319 } 2320 ASSERT(sarg->vap->va_mask & AT_NBLOCKS); 2321 na->space_used = (fattr4_space_used) DEV_BSIZE * 2322 (fattr4_space_used) sarg->vap->va_nblocks; 2323 break; 2324 case NFS4ATTR_SETIT: 2325 /* 2326 * read-only attr 2327 */ 2328 error = EINVAL; 2329 break; 2330 case NFS4ATTR_VERIT: 2331 ASSERT(sarg->vap->va_mask & AT_NBLOCKS); 2332 if (sarg->vap->va_nblocks != na->space_used) 2333 error = -1; /* no match */ 2334 break; 2335 case NFS4ATTR_FREEIT: 2336 break; 2337 } 2338 return (error); 2339 } 2340 2341 /* ARGSUSED */ 2342 static int 2343 rfs4_fattr4_system(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2344 union nfs4_attr_u *na) 2345 { 2346 return (ENOTSUP); 2347 } 2348 2349 /* ARGSUSED */ 2350 static int 2351 rfs4_fattr4_time_access(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2352 union nfs4_attr_u *na) 2353 { 2354 int error = 0; 2355 timestruc_t atime; 2356 2357 if (RFS4_MANDATTR_ONLY) 2358 return (ENOTSUP); 2359 2360 switch (cmd) { 2361 case NFS4ATTR_SUPPORTED: 2362 if (sarg->op == NFS4ATTR_SETIT) 2363 error = EINVAL; 2364 break; /* this attr is supported */ 2365 case NFS4ATTR_GETIT: 2366 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_ATIME)) { 2367 error = -1; /* may be okay if rdattr_error */ 2368 break; 2369 } 2370 ASSERT(sarg->vap->va_mask & AT_ATIME); 2371 error = nfs4_time_vton(&sarg->vap->va_atime, &na->time_access); 2372 break; 2373 case NFS4ATTR_SETIT: 2374 /* 2375 * read-only attr 2376 */ 2377 error = EINVAL; 2378 break; 2379 case NFS4ATTR_VERIT: 2380 ASSERT(sarg->vap->va_mask & AT_ATIME); 2381 error = nfs4_time_ntov(&na->time_access, &atime); 2382 if (error) 2383 break; 2384 if (bcmp(&atime, &sarg->vap->va_atime, sizeof (atime))) 2385 error = -1; /* no match */ 2386 break; 2387 case NFS4ATTR_FREEIT: 2388 break; 2389 } 2390 return (error); 2391 } 2392 2393 /* 2394 * XXX - need to support the setting of access time 2395 */ 2396 /* ARGSUSED */ 2397 static int 2398 rfs4_fattr4_time_access_set(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2399 union nfs4_attr_u *na) 2400 { 2401 int error = 0; 2402 settime4 *ta; 2403 2404 if (RFS4_MANDATTR_ONLY) 2405 return (ENOTSUP); 2406 2407 switch (cmd) { 2408 case NFS4ATTR_SUPPORTED: 2409 if ((sarg->op == NFS4ATTR_GETIT) || 2410 (sarg->op == NFS4ATTR_VERIT)) 2411 error = EINVAL; 2412 break; /* this attr is supported */ 2413 case NFS4ATTR_GETIT: 2414 case NFS4ATTR_VERIT: 2415 /* 2416 * write only attr 2417 */ 2418 error = EINVAL; 2419 break; 2420 case NFS4ATTR_SETIT: 2421 ASSERT(sarg->vap->va_mask & AT_ATIME); 2422 /* 2423 * Set access time (by server or by client) 2424 */ 2425 ta = &na->time_access_set; 2426 if (ta->set_it == SET_TO_CLIENT_TIME4) { 2427 error = nfs4_time_ntov(&ta->time, &sarg->vap->va_atime); 2428 } else if (ta->set_it == SET_TO_SERVER_TIME4) { 2429 gethrestime(&sarg->vap->va_atime); 2430 } else { 2431 error = EINVAL; 2432 } 2433 break; 2434 case NFS4ATTR_FREEIT: 2435 break; 2436 } 2437 return (error); 2438 } 2439 2440 /* ARGSUSED */ 2441 static int 2442 rfs4_fattr4_time_backup(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2443 union nfs4_attr_u *na) 2444 { 2445 return (ENOTSUP); 2446 } 2447 2448 /* ARGSUSED */ 2449 static int 2450 rfs4_fattr4_time_create(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2451 union nfs4_attr_u *na) 2452 { 2453 return (ENOTSUP); 2454 } 2455 2456 /* ARGSUSED */ 2457 static int 2458 rfs4_fattr4_time_delta(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2459 union nfs4_attr_u *na) 2460 { 2461 int error = 0; 2462 2463 if (RFS4_MANDATTR_ONLY) 2464 return (ENOTSUP); 2465 2466 switch (cmd) { 2467 case NFS4ATTR_SUPPORTED: 2468 if (sarg->op == NFS4ATTR_SETIT) 2469 error = EINVAL; 2470 break; /* this attr is supported */ 2471 case NFS4ATTR_GETIT: 2472 na->time_delta.seconds = 0; 2473 na->time_delta.nseconds = 1000; 2474 break; 2475 case NFS4ATTR_SETIT: 2476 /* 2477 * write only attr 2478 */ 2479 error = EINVAL; 2480 break; 2481 case NFS4ATTR_VERIT: 2482 if ((na->time_delta.seconds != 0) || 2483 (na->time_delta.nseconds != 1000)) 2484 error = -1; /* no match */ 2485 break; 2486 case NFS4ATTR_FREEIT: 2487 break; 2488 } 2489 return (error); 2490 } 2491 2492 /* ARGSUSED */ 2493 static int 2494 rfs4_fattr4_time_metadata(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2495 union nfs4_attr_u *na) 2496 { 2497 int error = 0; 2498 timestruc_t ctime; 2499 2500 if (RFS4_MANDATTR_ONLY) 2501 return (ENOTSUP); 2502 2503 switch (cmd) { 2504 case NFS4ATTR_SUPPORTED: 2505 if (sarg->op == NFS4ATTR_SETIT) 2506 error = EINVAL; 2507 break; /* this attr is supported */ 2508 case NFS4ATTR_GETIT: 2509 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_CTIME)) { 2510 error = -1; /* may be okay if rdattr_error */ 2511 break; 2512 } 2513 ASSERT(sarg->vap->va_mask & AT_CTIME); 2514 error = nfs4_time_vton(&sarg->vap->va_ctime, 2515 &na->time_metadata); 2516 break; 2517 case NFS4ATTR_SETIT: 2518 /* 2519 * read-only attr 2520 */ 2521 error = EINVAL; 2522 break; 2523 case NFS4ATTR_VERIT: 2524 ASSERT(sarg->vap->va_mask & AT_CTIME); 2525 error = nfs4_time_ntov(&na->time_metadata, &ctime); 2526 if (error) 2527 break; 2528 if (bcmp(&ctime, &sarg->vap->va_ctime, sizeof (ctime))) 2529 error = -1; /* no match */ 2530 break; 2531 case NFS4ATTR_FREEIT: 2532 break; 2533 } 2534 return (error); 2535 } 2536 2537 /* ARGSUSED */ 2538 static int 2539 rfs4_fattr4_time_modify(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2540 union nfs4_attr_u *na) 2541 { 2542 int error = 0; 2543 timestruc_t mtime; 2544 2545 if (RFS4_MANDATTR_ONLY) 2546 return (ENOTSUP); 2547 2548 switch (cmd) { 2549 case NFS4ATTR_SUPPORTED: 2550 if (sarg->op == NFS4ATTR_SETIT) 2551 error = EINVAL; 2552 break; /* this attr is supported */ 2553 case NFS4ATTR_GETIT: 2554 if (sarg->rdattr_error && !(sarg->vap->va_mask & AT_MTIME)) { 2555 error = -1; /* may be okay if rdattr_error */ 2556 break; 2557 } 2558 ASSERT(sarg->vap->va_mask & AT_MTIME); 2559 error = nfs4_time_vton(&sarg->vap->va_mtime, &na->time_modify); 2560 break; 2561 case NFS4ATTR_SETIT: 2562 /* 2563 * read-only attr 2564 */ 2565 error = EINVAL; 2566 break; 2567 case NFS4ATTR_VERIT: 2568 ASSERT(sarg->vap->va_mask & AT_MTIME); 2569 error = nfs4_time_ntov(&na->time_modify, &mtime); 2570 if (error) 2571 break; 2572 if (bcmp(&mtime, &sarg->vap->va_mtime, sizeof (mtime))) 2573 error = -1; /* no match */ 2574 break; 2575 case NFS4ATTR_FREEIT: 2576 break; 2577 } 2578 return (error); 2579 } 2580 2581 /* 2582 * XXX - need to add support for setting modify time 2583 */ 2584 /* ARGSUSED */ 2585 static int 2586 rfs4_fattr4_time_modify_set(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg, 2587 union nfs4_attr_u *na) 2588 { 2589 int error = 0; 2590 settime4 *tm; 2591 2592 if (RFS4_MANDATTR_ONLY) 2593 return (ENOTSUP); 2594 2595 switch (cmd) { 2596 case NFS4ATTR_SUPPORTED: 2597 if ((sarg->op == NFS4ATTR_GETIT) || 2598 (sarg->op == NFS4ATTR_VERIT)) 2599 error = EINVAL; 2600 break; /* this attr is supported */ 2601 case NFS4ATTR_GETIT: 2602 case NFS4ATTR_VERIT: 2603 /* 2604 * write only attr 2605 */ 2606 error = EINVAL; 2607 break; 2608 case NFS4ATTR_SETIT: 2609 ASSERT(sarg->vap->va_mask & AT_MTIME); 2610 /* 2611 * Set modify time (by server or by client) 2612 */ 2613 tm = &na->time_modify_set; 2614 if (tm->set_it == SET_TO_CLIENT_TIME4) { 2615 error = nfs4_time_ntov(&tm->time, &sarg->vap->va_mtime); 2616 sarg->flag = ATTR_UTIME; 2617 } else if (tm->set_it == SET_TO_SERVER_TIME4) { 2618 gethrestime(&sarg->vap->va_mtime); 2619 } else { 2620 error = EINVAL; 2621 } 2622 break; 2623 case NFS4ATTR_FREEIT: 2624 break; 2625 } 2626 return (error); 2627 } 2628 2629 2630 static void 2631 rfs4_ntov_init(void) 2632 { 2633 /* index must be same as corresponding FATTR4_* define */ 2634 nfs4_ntov_map[0].sv_getit = rfs4_fattr4_supported_attrs; 2635 nfs4_ntov_map[1].sv_getit = rfs4_fattr4_type; 2636 nfs4_ntov_map[2].sv_getit = rfs4_fattr4_fh_expire_type; 2637 nfs4_ntov_map[3].sv_getit = rfs4_fattr4_change; 2638 nfs4_ntov_map[4].sv_getit = rfs4_fattr4_size; 2639 nfs4_ntov_map[5].sv_getit = rfs4_fattr4_link_support; 2640 nfs4_ntov_map[6].sv_getit = rfs4_fattr4_symlink_support; 2641 nfs4_ntov_map[7].sv_getit = rfs4_fattr4_named_attr; 2642 nfs4_ntov_map[8].sv_getit = rfs4_fattr4_fsid; 2643 nfs4_ntov_map[9].sv_getit = rfs4_fattr4_unique_handles; 2644 nfs4_ntov_map[10].sv_getit = rfs4_fattr4_lease_time; 2645 nfs4_ntov_map[11].sv_getit = rfs4_fattr4_rdattr_error; 2646 nfs4_ntov_map[12].sv_getit = rfs4_fattr4_acl; 2647 nfs4_ntov_map[13].sv_getit = rfs4_fattr4_aclsupport; 2648 nfs4_ntov_map[14].sv_getit = rfs4_fattr4_archive; 2649 nfs4_ntov_map[15].sv_getit = rfs4_fattr4_cansettime; 2650 nfs4_ntov_map[16].sv_getit = rfs4_fattr4_case_insensitive; 2651 nfs4_ntov_map[17].sv_getit = rfs4_fattr4_case_preserving; 2652 nfs4_ntov_map[18].sv_getit = rfs4_fattr4_chown_restricted; 2653 nfs4_ntov_map[19].sv_getit = rfs4_fattr4_filehandle; 2654 nfs4_ntov_map[20].sv_getit = rfs4_fattr4_fileid; 2655 nfs4_ntov_map[21].sv_getit = rfs4_fattr4_files_avail; 2656 nfs4_ntov_map[22].sv_getit = rfs4_fattr4_files_free; 2657 nfs4_ntov_map[23].sv_getit = rfs4_fattr4_files_total; 2658 nfs4_ntov_map[24].sv_getit = rfs4_fattr4_fs_locations; 2659 nfs4_ntov_map[25].sv_getit = rfs4_fattr4_hidden; 2660 nfs4_ntov_map[26].sv_getit = rfs4_fattr4_homogeneous; 2661 nfs4_ntov_map[27].sv_getit = rfs4_fattr4_maxfilesize; 2662 nfs4_ntov_map[28].sv_getit = rfs4_fattr4_maxlink; 2663 nfs4_ntov_map[29].sv_getit = rfs4_fattr4_maxname; 2664 nfs4_ntov_map[30].sv_getit = rfs4_fattr4_maxread; 2665 nfs4_ntov_map[31].sv_getit = rfs4_fattr4_maxwrite; 2666 nfs4_ntov_map[32].sv_getit = rfs4_fattr4_mimetype; 2667 nfs4_ntov_map[33].sv_getit = rfs4_fattr4_mode; 2668 nfs4_ntov_map[34].sv_getit = rfs4_fattr4_no_trunc; 2669 nfs4_ntov_map[35].sv_getit = rfs4_fattr4_numlinks; 2670 nfs4_ntov_map[36].sv_getit = rfs4_fattr4_owner; 2671 nfs4_ntov_map[37].sv_getit = rfs4_fattr4_owner_group; 2672 nfs4_ntov_map[38].sv_getit = rfs4_fattr4_quota_avail_hard; 2673 nfs4_ntov_map[39].sv_getit = rfs4_fattr4_quota_avail_soft; 2674 nfs4_ntov_map[40].sv_getit = rfs4_fattr4_quota_used; 2675 nfs4_ntov_map[41].sv_getit = rfs4_fattr4_rawdev; 2676 nfs4_ntov_map[42].sv_getit = rfs4_fattr4_space_avail; 2677 nfs4_ntov_map[43].sv_getit = rfs4_fattr4_space_free; 2678 nfs4_ntov_map[44].sv_getit = rfs4_fattr4_space_total; 2679 nfs4_ntov_map[45].sv_getit = rfs4_fattr4_space_used; 2680 nfs4_ntov_map[46].sv_getit = rfs4_fattr4_system; 2681 nfs4_ntov_map[47].sv_getit = rfs4_fattr4_time_access; 2682 nfs4_ntov_map[48].sv_getit = rfs4_fattr4_time_access_set; 2683 nfs4_ntov_map[49].sv_getit = rfs4_fattr4_time_backup; 2684 nfs4_ntov_map[50].sv_getit = rfs4_fattr4_time_create; 2685 nfs4_ntov_map[51].sv_getit = rfs4_fattr4_time_delta; 2686 nfs4_ntov_map[52].sv_getit = rfs4_fattr4_time_metadata; 2687 nfs4_ntov_map[53].sv_getit = rfs4_fattr4_time_modify; 2688 nfs4_ntov_map[54].sv_getit = rfs4_fattr4_time_modify_set; 2689 nfs4_ntov_map[55].sv_getit = rfs4_fattr4_mounted_on_fileid; 2690 } 2691