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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 24 */ 25 26 /* 27 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31 #include <sys/param.h> 32 #include <sys/types.h> 33 #include <sys/systm.h> 34 #include <sys/cred.h> 35 #include <sys/buf.h> 36 #include <sys/vfs.h> 37 #include <sys/vnode.h> 38 #include <sys/uio.h> 39 #include <sys/errno.h> 40 #include <sys/sysmacros.h> 41 #include <sys/statvfs.h> 42 #include <sys/kmem.h> 43 #include <sys/dirent.h> 44 #include <rpc/types.h> 45 #include <rpc/auth.h> 46 #include <rpc/rpcsec_gss.h> 47 #include <rpc/svc.h> 48 #include <sys/strsubr.h> 49 #include <sys/strsun.h> 50 #include <sys/sdt.h> 51 52 #include <nfs/nfs.h> 53 #include <nfs/export.h> 54 #include <nfs/nfs4.h> 55 #include <nfs/nfs_cmd.h> 56 57 58 /* 59 * RFS4_MINLEN_ENTRY4: XDR-encoded size of smallest possible dirent. 60 * This is used to return NFS4ERR_TOOSMALL when clients specify 61 * maxcount that isn't large enough to hold the smallest possible 62 * XDR encoded dirent. 63 * 64 * sizeof cookie (8 bytes) + 65 * sizeof name_len (4 bytes) + 66 * sizeof smallest (padded) name (4 bytes) + 67 * sizeof bitmap4_len (12 bytes) + NOTE: we always encode len=2 bm4 68 * sizeof attrlist4_len (4 bytes) + 69 * sizeof next boolean (4 bytes) 70 * 71 * RFS4_MINLEN_RDDIR4: XDR-encoded size of READDIR op reply containing 72 * the smallest possible entry4 (assumes no attrs requested). 73 * sizeof nfsstat4 (4 bytes) + 74 * sizeof verifier4 (8 bytes) + 75 * sizeof entsecond_to_ry4list bool (4 bytes) + 76 * sizeof entry4 (36 bytes) + 77 * sizeof eof bool (4 bytes) 78 * 79 * RFS4_MINLEN_RDDIR_BUF: minimum length of buffer server will provide to 80 * VOP_READDIR. Its value is the size of the maximum possible dirent 81 * for solaris. The DIRENT64_RECLEN macro returns the size of dirent 82 * required for a given name length. MAXNAMELEN is the maximum 83 * filename length allowed in Solaris. The first two DIRENT64_RECLEN() 84 * macros are to allow for . and .. entries -- just a minor tweak to try 85 * and guarantee that buffer we give to VOP_READDIR will be large enough 86 * to hold ., .., and the largest possible solaris dirent64. 87 */ 88 #define RFS4_MINLEN_ENTRY4 36 89 #define RFS4_MINLEN_RDDIR4 (4 + NFS4_VERIFIER_SIZE + 4 + RFS4_MINLEN_ENTRY4 + 4) 90 #define RFS4_MINLEN_RDDIR_BUF \ 91 (DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2) + DIRENT64_RECLEN(MAXNAMELEN)) 92 93 94 #ifdef nextdp 95 #undef nextdp 96 #endif 97 #define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen)) 98 99 verifier4 Readdir4verf = 0x0; 100 101 static nfs_ftype4 vt_to_nf4[] = { 102 0, NF4REG, NF4DIR, NF4BLK, NF4CHR, NF4LNK, NF4FIFO, 0, 0, NF4SOCK, 0 103 }; 104 105 /* 106 * RFC 7530 Section 8.3.2 107 * Supported attributes for READDIR for the root of an absent filesystem. 108 */ 109 #define ABSENT_FS_ATTRS (FATTR4_FS_LOCATIONS_MASK | FATTR4_FSID_MASK | \ 110 FATTR4_MOUNTED_ON_FILEID_MASK | FATTR4_RDATTR_ERROR_MASK) 111 112 int 113 nfs4_readdir_getvp(vnode_t *dvp, char *d_name, vnode_t **vpp, 114 struct exportinfo **exi, struct svc_req *req, struct compound_state *cs, 115 int expseudo, bool_t *migrated) 116 { 117 int error; 118 int ismntpt; 119 fid_t fid; 120 vnode_t *vp, *pre_tvp; 121 nfsstat4 status; 122 struct exportinfo *newexi, *saveexi; 123 cred_t *scr; 124 125 *vpp = vp = NULL; 126 127 if (error = VOP_LOOKUP(dvp, d_name, &vp, NULL, 0, NULL, cs->cr, 128 NULL, NULL, NULL)) 129 return (error); 130 131 /* referral point ? */ 132 if (vn_is_nfs_reparse(vp, cs->cr) && !client_is_downrev(req)) { 133 DTRACE_PROBE2(nfs4serv__func__referral__moved, 134 vnode_t *, vp, char *, "nfs4_readdir_getvp"); 135 *migrated = TRUE; 136 *vpp = vp; 137 return (0); 138 } 139 140 /* Is this object mounted upon? */ 141 ismntpt = vn_ismntpt(vp); 142 143 /* 144 * Nothing more to do if object is not a mount point or 145 * a possible LOFS shadow of an LOFS mount (which won't 146 * have v_vfsmountedhere set) 147 */ 148 if (ismntpt == 0 && dvp->v_vfsp == vp->v_vfsp && expseudo == 0) { 149 *vpp = vp; 150 return (0); 151 } 152 153 if (ismntpt) { 154 /* 155 * Something is mounted here. Traverse and manage the 156 * namespace 157 */ 158 pre_tvp = vp; 159 VN_HOLD(pre_tvp); 160 161 if ((error = traverse(&vp)) != 0) { 162 VN_RELE(vp); 163 VN_RELE(pre_tvp); 164 return (error); 165 } 166 } 167 168 bzero(&fid, sizeof (fid)); 169 fid.fid_len = MAXFIDSZ; 170 171 /* 172 * If VOP_FID not supported by underlying fs (mntfs, procfs, 173 * etc.), then return attrs for stub instead of VROOT object. 174 * If it fails for any other reason, then return the error. 175 */ 176 if (error = VOP_FID(vp, &fid, NULL)) { 177 if (ismntpt == 0) { 178 VN_RELE(vp); 179 return (error); 180 } 181 182 if (error != ENOSYS && error != ENOTSUP) { 183 VN_RELE(vp); 184 VN_RELE(pre_tvp); 185 return (error); 186 } 187 /* go back to vnode that is "under" mount */ 188 VN_RELE(vp); 189 *vpp = pre_tvp; 190 return (0); 191 } 192 193 newexi = checkexport4(&vp->v_vfsp->vfs_fsid, &fid, vp); 194 if (newexi == NULL) { 195 if (ismntpt == 0) { 196 *vpp = vp; 197 } else { 198 VN_RELE(vp); 199 *vpp = pre_tvp; 200 } 201 return (0); 202 } 203 204 if (ismntpt) 205 VN_RELE(pre_tvp); 206 207 /* Save the exi and present the new one to checkauth4() */ 208 saveexi = cs->exi; 209 cs->exi = newexi; 210 211 /* Get the right cred like lookup does */ 212 scr = cs->cr; 213 cs->cr = crdup(cs->basecr); 214 215 status = call_checkauth4(cs, req); 216 217 crfree(cs->cr); 218 cs->cr = scr; 219 cs->exi = saveexi; 220 221 /* Reset what call_checkauth4() may have set */ 222 *cs->statusp = NFS4_OK; 223 224 if (status != NFS4_OK) { 225 VN_RELE(vp); 226 if (status == NFS4ERR_DELAY) 227 status = NFS4ERR_ACCESS; 228 return (status); 229 } 230 *vpp = vp; 231 *exi = newexi; 232 233 return (0); 234 } 235 236 /* This is the set of pathconf data for vfs */ 237 typedef struct { 238 uint64_t maxfilesize; 239 uint32_t maxlink; 240 uint32_t maxname; 241 } rfs4_pc_encode_t; 242 243 244 static int 245 rfs4_get_pc_encode(vnode_t *vp, rfs4_pc_encode_t *pce, bitmap4 ar, cred_t *cr) 246 { 247 int error; 248 ulong_t pc_val; 249 250 pce->maxfilesize = 0; 251 pce->maxlink = 0; 252 pce->maxname = 0; 253 254 if (ar & FATTR4_MAXFILESIZE_MASK) { 255 /* Maximum File Size */ 256 error = VOP_PATHCONF(vp, _PC_FILESIZEBITS, &pc_val, cr, NULL); 257 if (error) 258 return (error); 259 260 /* 261 * If the underlying file system does not support 262 * _PC_FILESIZEBITS, return a reasonable default. Note that 263 * error code on VOP_PATHCONF will be 0, even if the underlying 264 * file system does not support _PC_FILESIZEBITS. 265 */ 266 if (pc_val == (ulong_t)-1) { 267 pce->maxfilesize = MAXOFF32_T; 268 } else { 269 if (pc_val >= (sizeof (uint64_t) * 8)) 270 pce->maxfilesize = INT64_MAX; 271 else 272 pce->maxfilesize = ((1LL << (pc_val - 1)) - 1); 273 } 274 } 275 276 if (ar & FATTR4_MAXLINK_MASK) { 277 /* Maximum Link Count */ 278 error = VOP_PATHCONF(vp, _PC_LINK_MAX, &pc_val, cr, NULL); 279 if (error) 280 return (error); 281 282 pce->maxlink = pc_val; 283 } 284 285 if (ar & FATTR4_MAXNAME_MASK) { 286 /* Maximum Name Length */ 287 error = VOP_PATHCONF(vp, _PC_NAME_MAX, &pc_val, cr, NULL); 288 if (error) 289 return (error); 290 291 pce->maxname = pc_val; 292 } 293 294 return (0); 295 } 296 297 /* This is the set of statvfs data that is ready for encoding */ 298 typedef struct { 299 uint64_t space_avail; 300 uint64_t space_free; 301 uint64_t space_total; 302 u_longlong_t fa; 303 u_longlong_t ff; 304 u_longlong_t ft; 305 } rfs4_sb_encode_t; 306 307 static int 308 rfs4_get_sb_encode(vfs_t *vfsp, rfs4_sb_encode_t *psbe) 309 { 310 int error; 311 struct statvfs64 sb; 312 313 /* Grab the per filesystem info */ 314 if (error = VFS_STATVFS(vfsp, &sb)) { 315 return (error); 316 } 317 318 /* Calculate space available */ 319 if (sb.f_bavail != (fsblkcnt64_t)-1) { 320 psbe->space_avail = 321 (fattr4_space_avail) sb.f_frsize * 322 (fattr4_space_avail) sb.f_bavail; 323 } else { 324 psbe->space_avail = 325 (fattr4_space_avail) sb.f_bavail; 326 } 327 328 /* Calculate space free */ 329 if (sb.f_bfree != (fsblkcnt64_t)-1) { 330 psbe->space_free = 331 (fattr4_space_free) sb.f_frsize * 332 (fattr4_space_free) sb.f_bfree; 333 } else { 334 psbe->space_free = 335 (fattr4_space_free) sb.f_bfree; 336 } 337 338 /* Calculate space total */ 339 if (sb.f_blocks != (fsblkcnt64_t)-1) { 340 psbe->space_total = 341 (fattr4_space_total) sb.f_frsize * 342 (fattr4_space_total) sb.f_blocks; 343 } else { 344 psbe->space_total = 345 (fattr4_space_total) sb.f_blocks; 346 } 347 348 /* For use later on attr encode */ 349 psbe->fa = sb.f_favail; 350 psbe->ff = sb.f_ffree; 351 psbe->ft = sb.f_files; 352 353 return (0); 354 } 355 356 extern void rfs4_free_fs_locations4(fs_locations4 *); 357 358 /* 359 * If readdir only needs to return FILEID, we can take it from the 360 * dirent struct and save doing the lookup. 361 */ 362 /* ARGSUSED */ 363 void 364 rfs4_op_readdir(nfs_argop4 *argop, nfs_resop4 *resop, struct svc_req *req, 365 struct compound_state *cs) 366 { 367 READDIR4args *args = &argop->nfs_argop4_u.opreaddir; 368 READDIR4res *resp = &resop->nfs_resop4_u.opreaddir; 369 struct exportinfo *newexi = NULL; 370 int error; 371 mblk_t *mp; 372 uint_t mpcount; 373 int alloc_err = 0; 374 vnode_t *dvp = cs->vp; 375 vnode_t *vp; 376 vattr_t va; 377 struct dirent64 *dp; 378 rfs4_sb_encode_t dsbe, sbe; 379 int vfs_different; 380 int rddir_data_len, rddir_result_size; 381 caddr_t rddir_data; 382 offset_t rddir_next_offset; 383 int dircount; 384 int no_space; 385 int iseofdir; 386 uint_t eof; 387 struct iovec iov; 388 struct uio uio; 389 int tsize; 390 int check_visible; 391 struct exp_visible *visp; 392 393 uint32_t *ptr, *ptr_redzone; 394 uint32_t *beginning_ptr; 395 uint32_t *lastentry_ptr; 396 uint32_t *attrmask_ptr; 397 uint32_t *attr_offset_ptr; 398 uint32_t attr_length; 399 uint32_t rndup; 400 uint32_t namelen; 401 uint32_t rddirattr_error = 0; 402 int nents; 403 bitmap4 ar = args->attr_request & NFS4_SRV_RDDIR_SUPPORTED_ATTRS; 404 bitmap4 ae; 405 rfs4_pc_encode_t dpce, pce; 406 ulong_t pc_val; 407 uint64_t maxread; 408 uint64_t maxwrite; 409 uint_t true = TRUE; 410 uint_t false = FALSE; 411 uid_t lastuid; 412 gid_t lastgid; 413 int lu_set, lg_set; 414 utf8string owner, group; 415 int owner_error, group_error; 416 struct sockaddr *ca; 417 char *name = NULL; 418 nfsstat4 status = NFS4_OK; 419 420 DTRACE_NFSV4_2(op__readdir__start, struct compound_state *, cs, 421 READDIR4args *, args); 422 423 lu_set = lg_set = 0; 424 owner.utf8string_len = group.utf8string_len = 0; 425 owner.utf8string_val = group.utf8string_val = NULL; 426 427 resp->mblk = NULL; 428 429 /* Maximum read and write size */ 430 maxread = maxwrite = rfs4_tsize(req); 431 432 if (dvp == NULL) { 433 *cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE; 434 goto out; 435 } 436 437 /* 438 * If there is an unshared filesystem mounted on this vnode, 439 * do not allow readdir in this directory. 440 */ 441 if (vn_ismntpt(dvp)) { 442 *cs->statusp = resp->status = NFS4ERR_ACCESS; 443 goto out; 444 } 445 446 if (dvp->v_type != VDIR) { 447 *cs->statusp = resp->status = NFS4ERR_NOTDIR; 448 goto out; 449 } 450 451 if (args->maxcount <= RFS4_MINLEN_RDDIR4) { 452 *cs->statusp = resp->status = NFS4ERR_TOOSMALL; 453 goto out; 454 } 455 456 /* 457 * If write-only attrs are requested, then fail the readdir op 458 */ 459 if (args->attr_request & 460 (FATTR4_TIME_MODIFY_SET_MASK | FATTR4_TIME_ACCESS_SET_MASK)) { 461 *cs->statusp = resp->status = NFS4ERR_INVAL; 462 goto out; 463 } 464 465 error = VOP_ACCESS(dvp, VREAD, 0, cs->cr, NULL); 466 if (error) { 467 *cs->statusp = resp->status = puterrno4(error); 468 goto out; 469 } 470 471 if (args->cookieverf != Readdir4verf) { 472 *cs->statusp = resp->status = NFS4ERR_NOT_SAME; 473 goto out; 474 } 475 476 /* Is there pseudo-fs work that is needed for this readdir? */ 477 check_visible = PSEUDO(cs->exi) || 478 ! is_exported_sec(cs->nfsflavor, cs->exi) || 479 cs->access & CS_ACCESS_LIMITED; 480 481 /* Check the requested attributes and only do the work if needed */ 482 483 if (ar & (FATTR4_MAXFILESIZE_MASK | 484 FATTR4_MAXLINK_MASK | 485 FATTR4_MAXNAME_MASK)) { 486 if (error = rfs4_get_pc_encode(cs->vp, &dpce, ar, cs->cr)) { 487 *cs->statusp = resp->status = puterrno4(error); 488 goto out; 489 } 490 pce = dpce; 491 } 492 493 /* If there is statvfs data requested, pick it up once */ 494 if (ar & 495 (FATTR4_FILES_AVAIL_MASK | 496 FATTR4_FILES_FREE_MASK | 497 FATTR4_FILES_TOTAL_MASK | 498 FATTR4_FILES_AVAIL_MASK | 499 FATTR4_FILES_FREE_MASK | 500 FATTR4_FILES_TOTAL_MASK)) { 501 if (error = rfs4_get_sb_encode(dvp->v_vfsp, &dsbe)) { 502 *cs->statusp = resp->status = puterrno4(error); 503 goto out; 504 } 505 sbe = dsbe; 506 } 507 508 /* 509 * Max transfer size of the server is the absolute limite. 510 * If the client has decided to max out with something really 511 * tiny, then return toosmall. Otherwise, move forward and 512 * see if a single entry can be encoded. 513 */ 514 tsize = rfs4_tsize(req); 515 if (args->maxcount > tsize) 516 args->maxcount = tsize; 517 else if (args->maxcount < RFS4_MINLEN_RDDIR_BUF) { 518 if (args->maxcount < RFS4_MINLEN_ENTRY4) { 519 *cs->statusp = resp->status = NFS4ERR_TOOSMALL; 520 goto out; 521 } 522 } 523 524 /* 525 * How large should the mblk be for outgoing encoding. 526 */ 527 if (args->maxcount < MAXBSIZE) 528 mpcount = MAXBSIZE; 529 else 530 mpcount = args->maxcount; 531 532 /* 533 * mp will contain the data to be sent out in the readdir reply. 534 * It will be freed after the reply has been sent. 535 * Let's roundup the data to a BYTES_PER_XDR_UNIX multiple, 536 * so that the call to xdrmblk_putmblk() never fails. 537 */ 538 mp = allocb(RNDUP(mpcount), BPRI_MED); 539 540 if (mp == NULL) { 541 /* 542 * The allocation of the client's requested size has 543 * failed. It may be that the size is too large for 544 * current system utilization; step down to a "common" 545 * size and wait for the allocation to occur. 546 */ 547 if (mpcount > MAXBSIZE) 548 args->maxcount = mpcount = MAXBSIZE; 549 mp = allocb_wait(RNDUP(mpcount), BPRI_MED, 550 STR_NOSIG, &alloc_err); 551 } 552 553 ASSERT(mp != NULL); 554 ASSERT(alloc_err == 0); 555 556 resp->mblk = mp; 557 558 ptr = beginning_ptr = (uint32_t *)mp->b_datap->db_base; 559 560 /* 561 * The "redzone" at the end of the encoding buffer is used 562 * to deal with xdr encoding length. Instead of checking 563 * each encoding of an attribute value before it is done, 564 * make the assumption that it will fit into the buffer and 565 * check occasionally. 566 * 567 * The largest block of attributes that are encoded without 568 * checking the redzone is 18 * BYTES_PER_XDR_UNIT (72 bytes) 569 * "round" to 128 as the redzone size. 570 */ 571 if (args->maxcount < (mpcount - 128)) 572 ptr_redzone = 573 (uint32_t *)(((char *)ptr) + RNDUP(args->maxcount)); 574 else 575 ptr_redzone = 576 (uint32_t *)((((char *)ptr) + RNDUP(mpcount)) - 128); 577 578 /* 579 * Set the dircount; this will be used as the size for the 580 * readdir of the underlying filesystem. First make sure 581 * that it is large enough to do a reasonable readdir (client 582 * may have short changed us - it is an advisory number); 583 * then make sure that it isn't too large. 584 * After all of that, if maxcount is "small" then just use 585 * that for the dircount number. 586 */ 587 dircount = (args->dircount < MAXBSIZE) ? MAXBSIZE : args->dircount; 588 dircount = (dircount > tsize) ? tsize : dircount; 589 if (dircount > args->maxcount) 590 dircount = args->maxcount; 591 if (args->maxcount <= MAXBSIZE) { 592 if (args->maxcount < RFS4_MINLEN_RDDIR_BUF) 593 dircount = RFS4_MINLEN_RDDIR_BUF; 594 else 595 dircount = args->maxcount; 596 } 597 598 /* number of entries fully encoded in outgoing buffer */ 599 nents = 0; 600 601 /* ENCODE READDIR4res.cookieverf */ 602 IXDR_PUT_HYPER(ptr, Readdir4verf); 603 604 rddir_data_len = dircount; 605 rddir_data = kmem_alloc(rddir_data_len, KM_NOSLEEP); 606 if (rddir_data == NULL) { 607 /* The allocation failed; downsize and wait for it this time */ 608 if (rddir_data_len > MAXBSIZE) 609 rddir_data_len = dircount = MAXBSIZE; 610 rddir_data = kmem_alloc(rddir_data_len, KM_SLEEP); 611 } 612 613 rddir_next_offset = (offset_t)args->cookie; 614 615 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf; 616 617 readagain: 618 619 no_space = FALSE; 620 iseofdir = FALSE; 621 622 vp = NULL; 623 624 /* Move on to reading the directory contents */ 625 iov.iov_base = rddir_data; 626 iov.iov_len = rddir_data_len; 627 uio.uio_iov = &iov; 628 uio.uio_iovcnt = 1; 629 uio.uio_segflg = UIO_SYSSPACE; 630 uio.uio_extflg = UIO_COPY_CACHED; 631 uio.uio_loffset = rddir_next_offset; 632 uio.uio_resid = rddir_data_len; 633 634 (void) VOP_RWLOCK(dvp, V_WRITELOCK_FALSE, NULL); 635 636 error = VOP_READDIR(dvp, &uio, cs->cr, &iseofdir, NULL, 0); 637 638 VOP_RWUNLOCK(dvp, V_WRITELOCK_FALSE, NULL); 639 640 if (error) { 641 kmem_free((caddr_t)rddir_data, rddir_data_len); 642 freeb(resp->mblk); 643 resp->mblk = NULL; 644 resp->data_len = 0; 645 *cs->statusp = resp->status = puterrno4(error); 646 goto out; 647 } 648 649 650 rddir_result_size = rddir_data_len - uio.uio_resid; 651 652 /* No data were read. Check if we reached the end of the directory. */ 653 if (rddir_result_size == 0) { 654 /* encode the BOOLEAN marking no further entries */ 655 IXDR_PUT_U_INT32(ptr, false); 656 /* encode the BOOLEAN signifying end of directory */ 657 IXDR_PUT_U_INT32(ptr, iseofdir ? true : false); 658 resp->data_len = (char *)ptr - (char *)beginning_ptr; 659 resp->mblk->b_wptr += resp->data_len; 660 kmem_free((caddr_t)rddir_data, rddir_data_len); 661 *cs->statusp = resp->status = NFS4_OK; 662 goto out; 663 } 664 665 lastentry_ptr = ptr; 666 no_space = 0; 667 for (dp = (struct dirent64 *)rddir_data; 668 !no_space && rddir_result_size > 0; dp = nextdp(dp)) { 669 bool_t fs_migrated = FALSE; 670 671 /* reset visp */ 672 visp = NULL; 673 674 if (vp) { 675 VN_RELE(vp); 676 vp = NULL; 677 } 678 679 if (newexi) 680 newexi = NULL; 681 682 rddir_result_size -= dp->d_reclen; 683 684 /* skip "." and ".." entries */ 685 if (dp->d_ino == 0 || NFS_IS_DOTNAME(dp->d_name)) { 686 rddir_next_offset = dp->d_off; 687 continue; 688 } 689 690 if (check_visible && 691 !nfs_visible_inode(cs->exi, dp->d_ino, &visp)) { 692 rddir_next_offset = dp->d_off; 693 continue; 694 } 695 696 /* 697 * Only if the client requested attributes... 698 * If the VOP_LOOKUP fails ENOENT, then skip this entry 699 * for the readdir response. If there was another error, 700 * then set the rddirattr_error and the error will be 701 * encoded later in the "attributes" section. 702 */ 703 ae = ar; 704 if (ar == 0) 705 goto reencode_attrs; 706 707 error = nfs4_readdir_getvp(dvp, dp->d_name, 708 &vp, &newexi, req, cs, 709 visp != NULL ? visp->vis_exported : 0, &fs_migrated); 710 if (error == ENOENT) { 711 rddir_next_offset = dp->d_off; 712 continue; 713 } 714 715 rddirattr_error = error; 716 717 /* 718 * The vp obtained from above may be from a 719 * different filesystem mount and the vfs-like 720 * attributes should be obtained from that 721 * different vfs; only do this if appropriate. 722 */ 723 if (vp && 724 (vfs_different = (dvp->v_vfsp != vp->v_vfsp))) { 725 if (ae & (FATTR4_FILES_AVAIL_MASK | 726 FATTR4_FILES_FREE_MASK | 727 FATTR4_FILES_TOTAL_MASK | 728 FATTR4_FILES_AVAIL_MASK | 729 FATTR4_FILES_FREE_MASK | 730 FATTR4_FILES_TOTAL_MASK)) { 731 if (error = 732 rfs4_get_sb_encode(dvp->v_vfsp, 733 &sbe)) { 734 /* Remove attrs from encode */ 735 ae &= ~(FATTR4_FILES_AVAIL_MASK | 736 FATTR4_FILES_FREE_MASK | 737 FATTR4_FILES_TOTAL_MASK | 738 FATTR4_FILES_AVAIL_MASK | 739 FATTR4_FILES_FREE_MASK | 740 FATTR4_FILES_TOTAL_MASK); 741 rddirattr_error = error; 742 } 743 } 744 if (ae & (FATTR4_MAXFILESIZE_MASK | 745 FATTR4_MAXLINK_MASK | 746 FATTR4_MAXNAME_MASK)) { 747 if (error = rfs4_get_pc_encode(cs->vp, 748 &pce, ae, cs->cr)) { 749 ae &= ~(FATTR4_MAXFILESIZE_MASK | 750 FATTR4_MAXLINK_MASK | 751 FATTR4_MAXNAME_MASK); 752 rddirattr_error = error; 753 } 754 } 755 } 756 757 reencode_attrs: 758 /* encode the BOOLEAN for the existence of the next entry */ 759 IXDR_PUT_U_INT32(ptr, true); 760 /* encode the COOKIE for the entry */ 761 IXDR_PUT_U_HYPER(ptr, dp->d_off); 762 763 name = nfscmd_convname(ca, cs->exi, dp->d_name, 764 NFSCMD_CONV_OUTBOUND, MAXPATHLEN + 1); 765 766 if (name == NULL) { 767 rddir_next_offset = dp->d_off; 768 continue; 769 } 770 /* Calculate the dirent name length */ 771 namelen = strlen(name); 772 773 rndup = RNDUP(namelen) / BYTES_PER_XDR_UNIT; 774 775 /* room for LENGTH + string ? */ 776 if ((ptr + (1 + rndup)) > ptr_redzone) { 777 no_space = TRUE; 778 continue; 779 } 780 781 /* encode the LENGTH of the name */ 782 IXDR_PUT_U_INT32(ptr, namelen); 783 /* encode the RNDUP FILL first */ 784 ptr[rndup - 1] = 0; 785 /* encode the NAME of the entry */ 786 bcopy(name, (char *)ptr, namelen); 787 /* now bump the ptr after... */ 788 ptr += rndup; 789 790 if (name != dp->d_name) 791 kmem_free(name, MAXPATHLEN + 1); 792 793 /* 794 * Keep checking on the dircount to see if we have 795 * reached the limit; from the RFC, dircount is to be 796 * the XDR encoded limit of the cookie plus name. 797 * So the count is the name, XDR_UNIT of length for 798 * that name and 2 * XDR_UNIT bytes of cookie; 799 * However, use the regular DIRENT64 to match most 800 * client's APIs. 801 */ 802 dircount -= DIRENT64_RECLEN(namelen); 803 if (nents != 0 && dircount < 0) { 804 no_space = TRUE; 805 continue; 806 } 807 808 /* 809 * Attributes requested? 810 * Gather up the attribute info and the previous VOP_LOOKUP() 811 * succeeded; if an error occurs on the VOP_GETATTR() then 812 * return just the error (again if it is requested). 813 * Note that the previous VOP_LOOKUP() could have failed 814 * itself which leaves this code without anything for 815 * a VOP_GETATTR(). 816 * Also note that the readdir_attr_error is left in the 817 * encoding mask if requested and so is the mounted_on_fileid. 818 */ 819 if (ae != 0) { 820 if (!vp) { 821 ae = ar & (FATTR4_RDATTR_ERROR_MASK | 822 FATTR4_MOUNTED_ON_FILEID_MASK); 823 } else if (fs_migrated) { 824 /* 825 * RFC 7530 Section 8.3.2 826 * Restrict to actually available attributes in 827 * case of an absent filesystem. 828 */ 829 ae &= ABSENT_FS_ATTRS; 830 831 if (!(ae & FATTR4_FS_LOCATIONS_MASK)) 832 rddirattr_error = NFS4ERR_MOVED; 833 } else { 834 va.va_mask = AT_ALL; 835 rddirattr_error = 836 VOP_GETATTR(vp, &va, 0, cs->cr, NULL); 837 if (rddirattr_error) { 838 ae = ae & (FATTR4_RDATTR_ERROR_MASK | 839 FATTR4_MOUNTED_ON_FILEID_MASK); 840 } else { 841 /* 842 * We may lie about the object 843 * type for a referral 844 */ 845 if (vn_is_nfs_reparse(vp, cs->cr) && 846 client_is_downrev(req)) 847 va.va_type = VLNK; 848 } 849 } 850 851 /* RFC 7530 Section 8.3.2 and 16.24.4 */ 852 if (rddirattr_error != 0 && 853 !(ae & FATTR4_RDATTR_ERROR_MASK)) { 854 status = puterrno4(rddirattr_error); 855 goto out_free; 856 } 857 } 858 859 /* START OF ATTRIBUTE ENCODING */ 860 861 /* encode the LENGTH of the BITMAP4 array */ 862 IXDR_PUT_U_INT32(ptr, 2); 863 /* encode the BITMAP4 */ 864 attrmask_ptr = ptr; 865 IXDR_PUT_HYPER(ptr, ae); 866 attr_offset_ptr = ptr; 867 /* encode the default LENGTH of the attributes for entry */ 868 IXDR_PUT_U_INT32(ptr, 0); 869 870 if (ptr > ptr_redzone) { 871 no_space = TRUE; 872 continue; 873 } 874 875 /* Check if any of the first 32 attributes are being encoded */ 876 if (ae & 0xffffffff00000000) { 877 /* 878 * Redzone check is done at the end of this section. 879 * This particular section will encode a maximum of 880 * 18 * BYTES_PER_XDR_UNIT of data 881 */ 882 if (ae & 883 (FATTR4_SUPPORTED_ATTRS_MASK | 884 FATTR4_TYPE_MASK | 885 FATTR4_FH_EXPIRE_TYPE_MASK | 886 FATTR4_CHANGE_MASK | 887 FATTR4_SIZE_MASK | 888 FATTR4_LINK_SUPPORT_MASK | 889 FATTR4_SYMLINK_SUPPORT_MASK | 890 FATTR4_NAMED_ATTR_MASK | 891 FATTR4_FSID_MASK | 892 FATTR4_UNIQUE_HANDLES_MASK | 893 FATTR4_LEASE_TIME_MASK | 894 FATTR4_RDATTR_ERROR_MASK)) { 895 896 if (ae & FATTR4_SUPPORTED_ATTRS_MASK) { 897 IXDR_PUT_INT32(ptr, 2); 898 IXDR_PUT_HYPER(ptr, 899 rfs4_supported_attrs); 900 } 901 if (ae & FATTR4_TYPE_MASK) { 902 uint_t ftype = vt_to_nf4[va.va_type]; 903 if (dvp->v_flag & V_XATTRDIR) { 904 if (va.va_type == VDIR) 905 ftype = NF4ATTRDIR; 906 else 907 ftype = NF4NAMEDATTR; 908 } 909 IXDR_PUT_U_INT32(ptr, ftype); 910 } 911 if (ae & FATTR4_FH_EXPIRE_TYPE_MASK) { 912 uint_t expire_type = FH4_PERSISTENT; 913 IXDR_PUT_U_INT32(ptr, expire_type); 914 } 915 if (ae & FATTR4_CHANGE_MASK) { 916 u_longlong_t change; 917 NFS4_SET_FATTR4_CHANGE(change, 918 va.va_ctime); 919 if (visp != NULL) { 920 u_longlong_t visch; 921 NFS4_SET_FATTR4_CHANGE(visch, 922 visp->vis_change); 923 if (visch > change) 924 change = visch; 925 } 926 IXDR_PUT_HYPER(ptr, change); 927 } 928 if (ae & FATTR4_SIZE_MASK) { 929 u_longlong_t size = va.va_size; 930 IXDR_PUT_HYPER(ptr, size); 931 } 932 if (ae & FATTR4_LINK_SUPPORT_MASK) { 933 IXDR_PUT_U_INT32(ptr, true); 934 } 935 if (ae & FATTR4_SYMLINK_SUPPORT_MASK) { 936 IXDR_PUT_U_INT32(ptr, true); 937 } 938 if (ae & FATTR4_NAMED_ATTR_MASK) { 939 uint_t isit; 940 pc_val = FALSE; 941 int sattr_error; 942 943 if (!(vp->v_vfsp->vfs_flag & 944 VFS_XATTR)) { 945 isit = FALSE; 946 } else { 947 sattr_error = VOP_PATHCONF(vp, 948 _PC_SATTR_EXISTS, 949 &pc_val, cs->cr, NULL); 950 if (sattr_error || pc_val == 0) 951 (void) VOP_PATHCONF(vp, 952 _PC_XATTR_EXISTS, 953 &pc_val, 954 cs->cr, NULL); 955 } 956 isit = (pc_val ? TRUE : FALSE); 957 IXDR_PUT_U_INT32(ptr, isit); 958 } 959 if (ae & FATTR4_FSID_MASK) { 960 u_longlong_t major, minor; 961 struct exportinfo *exi; 962 963 exi = newexi ? newexi : cs->exi; 964 if (fs_migrated) { 965 major = 1; 966 minor = 0; 967 } else if (exi->exi_volatile_dev) { 968 int *pmaj = (int *)&major; 969 970 pmaj[0] = exi->exi_fsid.val[0]; 971 pmaj[1] = exi->exi_fsid.val[1]; 972 minor = 0; 973 } else { 974 major = getmajor(va.va_fsid); 975 minor = getminor(va.va_fsid); 976 } 977 IXDR_PUT_HYPER(ptr, major); 978 IXDR_PUT_HYPER(ptr, minor); 979 } 980 if (ae & FATTR4_UNIQUE_HANDLES_MASK) { 981 IXDR_PUT_U_INT32(ptr, false); 982 } 983 if (ae & FATTR4_LEASE_TIME_MASK) { 984 uint_t lt = rfs4_lease_time; 985 IXDR_PUT_U_INT32(ptr, lt); 986 } 987 if (ae & FATTR4_RDATTR_ERROR_MASK) { 988 rddirattr_error = 989 (rddirattr_error == 0 ? 990 0 : puterrno4(rddirattr_error)); 991 IXDR_PUT_U_INT32(ptr, rddirattr_error); 992 } 993 994 /* Check the redzone boundary */ 995 if (ptr > ptr_redzone) { 996 no_space = TRUE; 997 break; 998 } 999 } 1000 /* 1001 * Redzone check is done at the end of this section. 1002 * This particular section will encode a maximum of 1003 * 4 * BYTES_PER_XDR_UNIT of data. 1004 * NOTE: that if ACLs are supported that the 1005 * redzone calculations will need to change. 1006 */ 1007 if (ae & 1008 (FATTR4_ACL_MASK | 1009 FATTR4_ACLSUPPORT_MASK | 1010 FATTR4_ARCHIVE_MASK | 1011 FATTR4_CANSETTIME_MASK | 1012 FATTR4_CASE_INSENSITIVE_MASK | 1013 FATTR4_CASE_PRESERVING_MASK | 1014 FATTR4_CHOWN_RESTRICTED_MASK)) { 1015 1016 if (ae & FATTR4_ACL_MASK) { 1017 ASSERT(0); 1018 } 1019 if (ae & FATTR4_ACLSUPPORT_MASK) { 1020 ASSERT(0); 1021 } 1022 if (ae & FATTR4_ARCHIVE_MASK) { 1023 ASSERT(0); 1024 } 1025 if (ae & FATTR4_CANSETTIME_MASK) { 1026 IXDR_PUT_U_INT32(ptr, true); 1027 } 1028 if (ae & FATTR4_CASE_INSENSITIVE_MASK) { 1029 IXDR_PUT_U_INT32(ptr, false); 1030 } 1031 if (ae & FATTR4_CASE_PRESERVING_MASK) { 1032 IXDR_PUT_U_INT32(ptr, true); 1033 } 1034 if (ae & FATTR4_CHOWN_RESTRICTED_MASK) { 1035 uint_t isit; 1036 pc_val = FALSE; 1037 (void) VOP_PATHCONF(vp, 1038 _PC_CHOWN_RESTRICTED, 1039 &pc_val, cs->cr, NULL); 1040 isit = (pc_val ? TRUE : FALSE); 1041 IXDR_PUT_U_INT32(ptr, isit); 1042 } 1043 /* Check the redzone boundary */ 1044 if (ptr > ptr_redzone) { 1045 no_space = TRUE; 1046 break; 1047 } 1048 } 1049 /* 1050 * Redzone check is done before the filehandle 1051 * is encoded. 1052 */ 1053 if (ae & 1054 (FATTR4_FILEHANDLE_MASK | 1055 FATTR4_FILEID_MASK)) { 1056 1057 if (ae & FATTR4_FILEHANDLE_MASK) { 1058 struct { 1059 uint_t len; 1060 char *val; 1061 char fh[NFS_FH4_LEN]; 1062 } fh; 1063 fh.len = 0; 1064 fh.val = fh.fh; 1065 (void) makefh4((nfs_fh4 *)&fh, vp, 1066 (newexi ? newexi : cs->exi)); 1067 1068 if (dvp->v_flag & V_XATTRDIR) 1069 set_fh4_flag((nfs_fh4 *)&fh, 1070 FH4_NAMEDATTR); 1071 1072 if (!xdr_inline_encode_nfs_fh4( 1073 &ptr, ptr_redzone, 1074 (nfs_fh4_fmt_t *)fh.val)) { 1075 no_space = TRUE; 1076 break; 1077 } 1078 } 1079 if (ae & FATTR4_FILEID_MASK) { 1080 IXDR_PUT_HYPER(ptr, va.va_nodeid); 1081 } 1082 /* Check the redzone boundary */ 1083 if (ptr > ptr_redzone) { 1084 no_space = TRUE; 1085 break; 1086 } 1087 } 1088 1089 /* 1090 * Redzone check is done at the end of this section. 1091 * This particular section will encode a maximum of 1092 * 6 * BYTES_PER_XDR_UNIT of data. 1093 */ 1094 if (ae & 1095 (FATTR4_FILES_AVAIL_MASK | 1096 FATTR4_FILES_FREE_MASK | 1097 FATTR4_FILES_TOTAL_MASK)) { 1098 1099 if (ae & FATTR4_FILES_AVAIL_MASK) { 1100 IXDR_PUT_HYPER(ptr, sbe.fa); 1101 } 1102 if (ae & FATTR4_FILES_FREE_MASK) { 1103 IXDR_PUT_HYPER(ptr, sbe.ff); 1104 } 1105 if (ae & FATTR4_FILES_TOTAL_MASK) { 1106 IXDR_PUT_HYPER(ptr, sbe.ft); 1107 } 1108 1109 /* Check the redzone boundary */ 1110 if (ptr > ptr_redzone) { 1111 no_space = TRUE; 1112 break; 1113 } 1114 } 1115 1116 /* 1117 * Handle fs_locations separately. 1118 * This can be quite slow for referrals. Usually 1119 * clients don't use this attribute in readdir. 1120 */ 1121 if (ae & FATTR4_FS_LOCATIONS_MASK) { 1122 fs_locations4 *p; 1123 fs_locations4 fs; 1124 bool_t pushed; 1125 XDR xdr; 1126 1127 (void) memset(&fs, 0, sizeof (fs_locations4)); 1128 1129 ASSERT(vp); 1130 p = fetch_referral(vp, cs->cr); 1131 if (p != NULL) { 1132 fs = *p; 1133 kmem_free(p, sizeof (fs_locations4)); 1134 } 1135 1136 ASSERT(ptr_redzone >= ptr); 1137 ASSERT((uintptr_t)ptr_redzone - (uintptr_t)ptr 1138 <= UINT_MAX); 1139 xdrmem_create(&xdr, (caddr_t)ptr, 1140 (uintptr_t)ptr_redzone - (uintptr_t)ptr, 1141 XDR_ENCODE); 1142 1143 pushed = xdr_fattr4_fs_locations(&xdr, &fs); 1144 if (pushed) 1145 ptr = (uint32_t *)((char *)ptr + 1146 xdr_getpos(&xdr)); 1147 1148 xdr_destroy(&xdr); 1149 rfs4_free_fs_locations4(&fs); 1150 1151 if (!pushed || ptr > ptr_redzone) { 1152 no_space = TRUE; 1153 break; 1154 } 1155 } 1156 1157 if (ae & 1158 (FATTR4_HIDDEN_MASK | 1159 FATTR4_HOMOGENEOUS_MASK | 1160 FATTR4_MAXFILESIZE_MASK | 1161 FATTR4_MAXLINK_MASK | 1162 FATTR4_MAXNAME_MASK | 1163 FATTR4_MAXREAD_MASK | 1164 FATTR4_MAXWRITE_MASK)) { 1165 1166 if (ae & FATTR4_HIDDEN_MASK) { 1167 ASSERT(0); 1168 } 1169 if (ae & FATTR4_HOMOGENEOUS_MASK) { 1170 IXDR_PUT_U_INT32(ptr, true); 1171 } 1172 if (ae & FATTR4_MAXFILESIZE_MASK) { 1173 IXDR_PUT_HYPER(ptr, pce.maxfilesize); 1174 } 1175 if (ae & FATTR4_MAXLINK_MASK) { 1176 IXDR_PUT_U_INT32(ptr, pce.maxlink); 1177 } 1178 if (ae & FATTR4_MAXNAME_MASK) { 1179 IXDR_PUT_U_INT32(ptr, pce.maxname); 1180 } 1181 if (ae & FATTR4_MAXREAD_MASK) { 1182 IXDR_PUT_HYPER(ptr, maxread); 1183 } 1184 if (ae & FATTR4_MAXWRITE_MASK) { 1185 IXDR_PUT_HYPER(ptr, maxwrite); 1186 } 1187 /* Check the redzone boundary */ 1188 if (ptr > ptr_redzone) { 1189 no_space = TRUE; 1190 break; 1191 } 1192 } 1193 } 1194 1195 if (ae & 0x00000000ffffffff) { 1196 /* 1197 * Redzone check is done at the end of this section. 1198 * This particular section will encode a maximum of 1199 * 3 * BYTES_PER_XDR_UNIT of data. 1200 */ 1201 if (ae & 1202 (FATTR4_MIMETYPE_MASK | 1203 FATTR4_MODE_MASK | 1204 FATTR4_NO_TRUNC_MASK | 1205 FATTR4_NUMLINKS_MASK)) { 1206 1207 if (ae & FATTR4_MIMETYPE_MASK) { 1208 ASSERT(0); 1209 } 1210 if (ae & FATTR4_MODE_MASK) { 1211 uint_t m = va.va_mode; 1212 IXDR_PUT_U_INT32(ptr, m); 1213 } 1214 if (ae & FATTR4_NO_TRUNC_MASK) { 1215 IXDR_PUT_U_INT32(ptr, true); 1216 } 1217 if (ae & FATTR4_NUMLINKS_MASK) { 1218 IXDR_PUT_U_INT32(ptr, va.va_nlink); 1219 } 1220 /* Check the redzone boundary */ 1221 if (ptr > ptr_redzone) { 1222 no_space = TRUE; 1223 break; 1224 } 1225 } 1226 /* 1227 * Redzone check is done before the encoding of the 1228 * owner string since the length is indeterminate. 1229 */ 1230 if (ae & FATTR4_OWNER_MASK) { 1231 if (!lu_set) { 1232 owner_error = nfs_idmap_uid_str( 1233 va.va_uid, &owner, TRUE); 1234 if (!owner_error) { 1235 lu_set = TRUE; 1236 lastuid = va.va_uid; 1237 } 1238 } else if (va.va_uid != lastuid) { 1239 if (owner.utf8string_len != 0) { 1240 kmem_free(owner.utf8string_val, 1241 owner.utf8string_len); 1242 owner.utf8string_len = 0; 1243 owner.utf8string_val = NULL; 1244 } 1245 owner_error = nfs_idmap_uid_str( 1246 va.va_uid, &owner, TRUE); 1247 if (!owner_error) { 1248 lastuid = va.va_uid; 1249 } else { 1250 lu_set = FALSE; 1251 } 1252 } 1253 if (!owner_error) { 1254 if ((ptr + 1255 (owner.utf8string_len / 1256 BYTES_PER_XDR_UNIT) 1257 + 2) > ptr_redzone) { 1258 no_space = TRUE; 1259 break; 1260 } 1261 /* encode the LENGTH of owner string */ 1262 IXDR_PUT_U_INT32(ptr, 1263 owner.utf8string_len); 1264 /* encode the RNDUP FILL first */ 1265 rndup = RNDUP(owner.utf8string_len) / 1266 BYTES_PER_XDR_UNIT; 1267 ptr[rndup - 1] = 0; 1268 /* encode the OWNER */ 1269 bcopy(owner.utf8string_val, ptr, 1270 owner.utf8string_len); 1271 ptr += rndup; 1272 } 1273 } 1274 /* 1275 * Redzone check is done before the encoding of the 1276 * group string since the length is indeterminate. 1277 */ 1278 if (ae & FATTR4_OWNER_GROUP_MASK) { 1279 if (!lg_set) { 1280 group_error = 1281 nfs_idmap_gid_str(va.va_gid, 1282 &group, TRUE); 1283 if (!group_error) { 1284 lg_set = TRUE; 1285 lastgid = va.va_gid; 1286 } 1287 } else if (va.va_gid != lastgid) { 1288 if (group.utf8string_len != 0) { 1289 kmem_free( 1290 group.utf8string_val, 1291 group.utf8string_len); 1292 group.utf8string_len = 0; 1293 group.utf8string_val = NULL; 1294 } 1295 group_error = 1296 nfs_idmap_gid_str(va.va_gid, 1297 &group, TRUE); 1298 if (!group_error) 1299 lastgid = va.va_gid; 1300 else 1301 lg_set = FALSE; 1302 } 1303 if (!group_error) { 1304 if ((ptr + 1305 (group.utf8string_len / 1306 BYTES_PER_XDR_UNIT) 1307 + 2) > ptr_redzone) { 1308 no_space = TRUE; 1309 break; 1310 } 1311 /* encode the LENGTH of owner string */ 1312 IXDR_PUT_U_INT32(ptr, 1313 group.utf8string_len); 1314 /* encode the RNDUP FILL first */ 1315 rndup = RNDUP(group.utf8string_len) / 1316 BYTES_PER_XDR_UNIT; 1317 ptr[rndup - 1] = 0; 1318 /* encode the OWNER */ 1319 bcopy(group.utf8string_val, ptr, 1320 group.utf8string_len); 1321 ptr += rndup; 1322 } 1323 } 1324 if (ae & 1325 (FATTR4_QUOTA_AVAIL_HARD_MASK | 1326 FATTR4_QUOTA_AVAIL_SOFT_MASK | 1327 FATTR4_QUOTA_USED_MASK)) { 1328 if (ae & FATTR4_QUOTA_AVAIL_HARD_MASK) { 1329 ASSERT(0); 1330 } 1331 if (ae & FATTR4_QUOTA_AVAIL_SOFT_MASK) { 1332 ASSERT(0); 1333 } 1334 if (ae & FATTR4_QUOTA_USED_MASK) { 1335 ASSERT(0); 1336 } 1337 } 1338 /* 1339 * Redzone check is done at the end of this section. 1340 * This particular section will encode a maximum of 1341 * 10 * BYTES_PER_XDR_UNIT of data. 1342 */ 1343 if (ae & 1344 (FATTR4_RAWDEV_MASK | 1345 FATTR4_SPACE_AVAIL_MASK | 1346 FATTR4_SPACE_FREE_MASK | 1347 FATTR4_SPACE_TOTAL_MASK | 1348 FATTR4_SPACE_USED_MASK | 1349 FATTR4_SYSTEM_MASK)) { 1350 1351 if (ae & FATTR4_RAWDEV_MASK) { 1352 fattr4_rawdev rd; 1353 rd.specdata1 = 1354 (uint32)getmajor(va.va_rdev); 1355 rd.specdata2 = 1356 (uint32)getminor(va.va_rdev); 1357 IXDR_PUT_U_INT32(ptr, rd.specdata1); 1358 IXDR_PUT_U_INT32(ptr, rd.specdata2); 1359 } 1360 if (ae & FATTR4_SPACE_AVAIL_MASK) { 1361 IXDR_PUT_HYPER(ptr, sbe.space_avail); 1362 } 1363 if (ae & FATTR4_SPACE_FREE_MASK) { 1364 IXDR_PUT_HYPER(ptr, sbe.space_free); 1365 } 1366 if (ae & FATTR4_SPACE_TOTAL_MASK) { 1367 IXDR_PUT_HYPER(ptr, sbe.space_total); 1368 } 1369 if (ae & FATTR4_SPACE_USED_MASK) { 1370 u_longlong_t su; 1371 su = (fattr4_space_used) DEV_BSIZE * 1372 (fattr4_space_used) va.va_nblocks; 1373 IXDR_PUT_HYPER(ptr, su); 1374 } 1375 if (ae & FATTR4_SYSTEM_MASK) { 1376 ASSERT(0); 1377 } 1378 /* Check the redzone boundary */ 1379 if (ptr > ptr_redzone) { 1380 no_space = TRUE; 1381 break; 1382 } 1383 } 1384 /* 1385 * Redzone check is done at the end of this section. 1386 * This particular section will encode a maximum of 1387 * 14 * BYTES_PER_XDR_UNIT of data. 1388 */ 1389 if (ae & 1390 (FATTR4_TIME_ACCESS_MASK | 1391 FATTR4_TIME_ACCESS_SET_MASK | 1392 FATTR4_TIME_BACKUP_MASK | 1393 FATTR4_TIME_CREATE_MASK | 1394 FATTR4_TIME_DELTA_MASK | 1395 FATTR4_TIME_METADATA_MASK | 1396 FATTR4_TIME_MODIFY_MASK | 1397 FATTR4_TIME_MODIFY_SET_MASK | 1398 FATTR4_MOUNTED_ON_FILEID_MASK)) { 1399 1400 if (ae & FATTR4_TIME_ACCESS_MASK) { 1401 u_longlong_t sec = 1402 (u_longlong_t)va.va_atime.tv_sec; 1403 uint_t nsec = 1404 (uint_t)va.va_atime.tv_nsec; 1405 IXDR_PUT_HYPER(ptr, sec); 1406 IXDR_PUT_INT32(ptr, nsec); 1407 } 1408 if (ae & FATTR4_TIME_ACCESS_SET_MASK) { 1409 ASSERT(0); 1410 } 1411 if (ae & FATTR4_TIME_BACKUP_MASK) { 1412 ASSERT(0); 1413 } 1414 if (ae & FATTR4_TIME_CREATE_MASK) { 1415 ASSERT(0); 1416 } 1417 if (ae & FATTR4_TIME_DELTA_MASK) { 1418 u_longlong_t sec = 0; 1419 uint_t nsec = 1000; 1420 IXDR_PUT_HYPER(ptr, sec); 1421 IXDR_PUT_INT32(ptr, nsec); 1422 } 1423 if (ae & FATTR4_TIME_METADATA_MASK) { 1424 u_longlong_t sec = 1425 (u_longlong_t)va.va_ctime.tv_sec; 1426 uint_t nsec = 1427 (uint_t)va.va_ctime.tv_nsec; 1428 IXDR_PUT_HYPER(ptr, sec); 1429 IXDR_PUT_INT32(ptr, nsec); 1430 } 1431 if (ae & FATTR4_TIME_MODIFY_MASK) { 1432 u_longlong_t sec = 1433 (u_longlong_t)va.va_mtime.tv_sec; 1434 uint_t nsec = 1435 (uint_t)va.va_mtime.tv_nsec; 1436 IXDR_PUT_HYPER(ptr, sec); 1437 IXDR_PUT_INT32(ptr, nsec); 1438 } 1439 if (ae & FATTR4_TIME_MODIFY_SET_MASK) { 1440 ASSERT(0); 1441 } 1442 if (ae & FATTR4_MOUNTED_ON_FILEID_MASK) { 1443 IXDR_PUT_HYPER(ptr, dp->d_ino); 1444 } 1445 /* Check the redzone boundary */ 1446 if (ptr > ptr_redzone) { 1447 no_space = TRUE; 1448 break; 1449 } 1450 } 1451 } 1452 1453 /* Reset to directory's vfs info when encoding complete */ 1454 if (vfs_different) { 1455 dsbe = sbe; 1456 dpce = pce; 1457 vfs_different = 0; 1458 } 1459 1460 /* "go back" and encode the attributes' length */ 1461 attr_length = 1462 (char *)ptr - 1463 (char *)attr_offset_ptr - 1464 BYTES_PER_XDR_UNIT; 1465 IXDR_PUT_U_INT32(attr_offset_ptr, attr_length); 1466 1467 /* 1468 * If there was trouble obtaining a mapping for either 1469 * the owner or group attributes, then remove them from 1470 * bitmap4 for this entry and reset the bitmap value 1471 * in the data stream. 1472 */ 1473 if (owner_error || group_error) { 1474 if (owner_error) 1475 ae &= ~FATTR4_OWNER_MASK; 1476 if (group_error) 1477 ae &= ~FATTR4_OWNER_GROUP_MASK; 1478 IXDR_PUT_HYPER(attrmask_ptr, ae); 1479 } 1480 1481 /* END OF ATTRIBUTE ENCODING */ 1482 1483 lastentry_ptr = ptr; 1484 nents++; 1485 rddir_next_offset = dp->d_off; 1486 } 1487 1488 /* 1489 * Check for the case that another VOP_READDIR() has to be done. 1490 * - no space encoding error 1491 * - no entry successfully encoded 1492 * - still more directory to read 1493 */ 1494 if (!no_space && nents == 0 && !iseofdir) 1495 goto readagain; 1496 1497 /* 1498 * If no_space is set then we terminated prematurely, 1499 * rewind to the last entry and this can never be EOF. 1500 */ 1501 if (no_space) { 1502 ptr = lastentry_ptr; 1503 eof = FALSE; /* ended encoded prematurely */ 1504 } else { 1505 eof = (iseofdir ? TRUE : FALSE); 1506 } 1507 1508 /* 1509 * If we have entries, always return them, otherwise only error 1510 * if we ran out of space. 1511 */ 1512 if (nents || !no_space) { 1513 ASSERT(ptr != NULL); 1514 /* encode the BOOLEAN marking no further entries */ 1515 IXDR_PUT_U_INT32(ptr, false); 1516 /* encode the BOOLEAN signifying end of directory */ 1517 IXDR_PUT_U_INT32(ptr, eof); 1518 1519 resp->data_len = (char *)ptr - (char *)beginning_ptr; 1520 resp->mblk->b_wptr += resp->data_len; 1521 } else { 1522 status = NFS4ERR_TOOSMALL; 1523 } 1524 1525 out_free: 1526 if (status != NFS4_OK) { 1527 freeb(mp); 1528 resp->mblk = NULL; 1529 resp->data_len = 0; 1530 } 1531 1532 *cs->statusp = resp->status = status; 1533 1534 kmem_free((caddr_t)rddir_data, rddir_data_len); 1535 if (vp) 1536 VN_RELE(vp); 1537 if (owner.utf8string_len != 0) 1538 kmem_free(owner.utf8string_val, owner.utf8string_len); 1539 if (group.utf8string_len != 0) 1540 kmem_free(group.utf8string_val, group.utf8string_len); 1541 1542 out: 1543 DTRACE_NFSV4_2(op__readdir__done, struct compound_state *, cs, 1544 READDIR4res *, resp); 1545 } 1546