1 /* $NetBSD: ulfs_lookup.c,v 1.41 2017/06/10 05:29:36 maya Exp $ */ 2 /* from NetBSD: ufs_lookup.c,v 1.135 2015/07/11 11:04:48 mlelstv */ 3 4 /* 5 * Copyright (c) 1989, 1993 6 * The Regents of the University of California. All rights reserved. 7 * (c) UNIX System Laboratories, Inc. 8 * All or some portions of this file are derived from material licensed 9 * to the University of California by American Telephone and Telegraph 10 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 11 * the permission of UNIX System Laboratories, Inc. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * @(#)ufs_lookup.c 8.9 (Berkeley) 8/11/94 38 */ 39 40 #include <sys/cdefs.h> 41 __KERNEL_RCSID(0, "$NetBSD: ulfs_lookup.c,v 1.41 2017/06/10 05:29:36 maya Exp $"); 42 43 #ifdef _KERNEL_OPT 44 #include "opt_lfs.h" 45 #endif 46 47 #include <sys/param.h> 48 #include <sys/systm.h> 49 #include <sys/namei.h> 50 #include <sys/buf.h> 51 #include <sys/file.h> 52 #include <sys/stat.h> 53 #include <sys/mount.h> 54 #include <sys/vnode.h> 55 #include <sys/kernel.h> 56 #include <sys/kauth.h> 57 #include <sys/proc.h> 58 #include <sys/kmem.h> 59 60 #include <ufs/lfs/lfs.h> 61 #include <ufs/lfs/lfs_accessors.h> 62 #include <ufs/lfs/lfs_extern.h> 63 64 #include <ufs/lfs/ulfs_inode.h> 65 #ifdef LFS_DIRHASH 66 #include <ufs/lfs/ulfs_dirhash.h> 67 #endif 68 #include <ufs/lfs/ulfsmount.h> 69 #include <ufs/lfs/ulfs_extern.h> 70 #include <ufs/lfs/ulfs_bswap.h> 71 72 #include <miscfs/genfs/genfs.h> 73 74 #ifdef DIAGNOSTIC 75 int lfs_dirchk = 1; 76 #else 77 int lfs_dirchk = 0; 78 #endif 79 80 /* 81 * Convert a component of a pathname into a pointer to a locked inode. 82 * This is a very central and rather complicated routine. 83 * If the file system is not maintained in a strict tree hierarchy, 84 * this can result in a deadlock situation (see comments in code below). 85 * 86 * The cnp->cn_nameiop argument is LOOKUP, CREATE, RENAME, or DELETE depending 87 * on whether the name is to be looked up, created, renamed, or deleted. 88 * When CREATE, RENAME, or DELETE is specified, information usable in 89 * creating, renaming, or deleting a directory entry may be calculated. 90 * If flag has LOCKPARENT or'ed into it and the target of the pathname 91 * exists, lookup returns both the target and its parent directory locked. 92 * When creating or renaming and LOCKPARENT is specified, the target may 93 * not be ".". When deleting and LOCKPARENT is specified, the target may 94 * be "."., but the caller must check to ensure it does an vrele and vput 95 * instead of two vputs. 96 * 97 * Overall outline of ulfs_lookup: 98 * 99 * check accessibility of directory 100 * look for name in cache, if found, then if at end of path 101 * and deleting or creating, drop it, else return name 102 * search for name in directory, to found or notfound 103 * notfound: 104 * if creating, return locked directory, leaving info on available slots 105 * else return error 106 * found: 107 * if at end of path and deleting, return information to allow delete 108 * if at end of path and rewriting (RENAME and LOCKPARENT), lock target 109 * inode and return info to allow rewrite 110 * if not at end, add name to cache; if at end and neither creating 111 * nor deleting, add name to cache 112 */ 113 int 114 ulfs_lookup(void *v) 115 { 116 struct vop_lookup_v2_args /* { 117 struct vnode *a_dvp; 118 struct vnode **a_vpp; 119 struct componentname *a_cnp; 120 } */ *ap = v; 121 struct vnode *vdp = ap->a_dvp; /* vnode for directory being searched */ 122 struct inode *dp = VTOI(vdp); /* inode for directory being searched */ 123 struct buf *bp; /* a buffer of directory entries */ 124 LFS_DIRHEADER *ep; /* the current directory entry */ 125 int entryoffsetinblock; /* offset of ep in bp's buffer */ 126 enum { 127 NONE, /* need to search a slot for our new entry */ 128 COMPACT, /* a compaction can make a slot in the current 129 DIRBLKSIZ block */ 130 FOUND, /* found a slot (or no need to search) */ 131 } slotstatus; 132 doff_t slotoffset; /* offset of area with free space. 133 a special value -1 for invalid */ 134 int slotsize; /* size of area at slotoffset */ 135 int slotfreespace; /* accumulated amount of space free in 136 the current DIRBLKSIZ block */ 137 int slotneeded; /* size of the entry we're seeking */ 138 int numdirpasses; /* strategy for directory search */ 139 doff_t endsearch; /* offset to end directory search */ 140 doff_t prevoff; /* previous value of ulr_offset */ 141 struct vnode *tdp; /* returned by vcache_get */ 142 doff_t enduseful; /* pointer past last used dir slot. 143 used for directory truncation. */ 144 u_long bmask; /* block offset mask */ 145 int error; 146 struct vnode **vpp = ap->a_vpp; 147 struct componentname *cnp = ap->a_cnp; 148 kauth_cred_t cred = cnp->cn_cred; 149 int flags; 150 int nameiop = cnp->cn_nameiop; 151 struct lfs *fs = dp->i_lfs; 152 int dirblksiz = fs->um_dirblksiz; 153 ino_t foundino; 154 struct ulfs_lookup_results *results; 155 int iswhiteout; /* temp result from cache_lookup() */ 156 157 flags = cnp->cn_flags; 158 159 bp = NULL; 160 slotoffset = -1; 161 *vpp = NULL; 162 endsearch = 0; /* silence compiler warning */ 163 164 /* 165 * Produce the auxiliary lookup results into i_crap. Increment 166 * its serial number so elsewhere we can tell if we're using 167 * stale results. This should not be done this way. XXX. 168 */ 169 results = &dp->i_crap; 170 dp->i_crapcounter++; 171 172 /* 173 * Check accessiblity of directory. 174 */ 175 if ((error = VOP_ACCESS(vdp, VEXEC, cred)) != 0) 176 return (error); 177 178 if ((flags & ISLASTCN) && (vdp->v_mount->mnt_flag & MNT_RDONLY) && 179 (nameiop == DELETE || nameiop == RENAME)) 180 return (EROFS); 181 182 /* 183 * We now have a segment name to search for, and a directory to search. 184 * 185 * Before tediously performing a linear scan of the directory, 186 * check the name cache to see if the directory/name pair 187 * we are looking for is known already. 188 */ 189 if (cache_lookup(vdp, cnp->cn_nameptr, cnp->cn_namelen, 190 cnp->cn_nameiop, cnp->cn_flags, &iswhiteout, vpp)) { 191 if (iswhiteout) { 192 cnp->cn_flags |= ISWHITEOUT; 193 } 194 return *vpp == NULLVP ? ENOENT : 0; 195 } 196 if (iswhiteout) { 197 /* 198 * The namecache set iswhiteout without finding a 199 * cache entry. As of this writing (20121014), this 200 * can happen if there was a whiteout entry that has 201 * been invalidated by the lookup. It is not clear if 202 * it is correct to set ISWHITEOUT in this case or 203 * not; however, doing so retains the prior behavior, 204 * so we'll go with that until some clearer answer 205 * appears. XXX 206 */ 207 cnp->cn_flags |= ISWHITEOUT; 208 } 209 210 /* 211 * Suppress search for slots unless creating 212 * file and at end of pathname, in which case 213 * we watch for a place to put the new file in 214 * case it doesn't already exist. 215 */ 216 slotstatus = FOUND; 217 slotfreespace = slotsize = slotneeded = 0; 218 if ((nameiop == CREATE || nameiop == RENAME) && (flags & ISLASTCN)) { 219 slotstatus = NONE; 220 slotneeded = LFS_DIRECTSIZ(fs, cnp->cn_namelen); 221 } 222 223 /* 224 * If there is cached information on a previous search of 225 * this directory, pick up where we last left off. 226 * We cache only lookups as these are the most common 227 * and have the greatest payoff. Caching CREATE has little 228 * benefit as it usually must search the entire directory 229 * to determine that the entry does not exist. Caching the 230 * location of the last DELETE or RENAME has not reduced 231 * profiling time and hence has been removed in the interest 232 * of simplicity. 233 */ 234 bmask = vdp->v_mount->mnt_stat.f_iosize - 1; 235 236 #ifdef LFS_DIRHASH 237 /* 238 * Use dirhash for fast operations on large directories. The logic 239 * to determine whether to hash the directory is contained within 240 * ulfsdirhash_build(); a zero return means that it decided to hash 241 * this directory and it successfully built up the hash table. 242 */ 243 if (ulfsdirhash_build(dp) == 0) { 244 /* Look for a free slot if needed. */ 245 enduseful = dp->i_size; 246 if (slotstatus != FOUND) { 247 slotoffset = ulfsdirhash_findfree(dp, slotneeded, 248 &slotsize); 249 if (slotoffset >= 0) { 250 slotstatus = COMPACT; 251 enduseful = ulfsdirhash_enduseful(dp); 252 if (enduseful < 0) 253 enduseful = dp->i_size; 254 } 255 } 256 /* Look up the component. */ 257 numdirpasses = 1; 258 entryoffsetinblock = 0; /* silence compiler warning */ 259 switch (ulfsdirhash_lookup(dp, cnp->cn_nameptr, cnp->cn_namelen, 260 &results->ulr_offset, &bp, nameiop == DELETE ? &prevoff : NULL)) { 261 case 0: 262 ep = (LFS_DIRHEADER *)((char *)bp->b_data + 263 (results->ulr_offset & bmask)); 264 goto foundentry; 265 case ENOENT: 266 results->ulr_offset = roundup(dp->i_size, dirblksiz); 267 goto notfound; 268 default: 269 /* Something failed; just do a linear search. */ 270 break; 271 } 272 } 273 #endif /* LFS_DIRHASH */ 274 275 if (nameiop != LOOKUP || results->ulr_diroff == 0 || 276 results->ulr_diroff >= dp->i_size) { 277 entryoffsetinblock = 0; 278 results->ulr_offset = 0; 279 numdirpasses = 1; 280 } else { 281 results->ulr_offset = results->ulr_diroff; 282 if ((entryoffsetinblock = results->ulr_offset & bmask) && 283 (error = ulfs_blkatoff(vdp, (off_t)results->ulr_offset, 284 NULL, &bp, false))) 285 goto out; 286 numdirpasses = 2; 287 namecache_count_2passes(); 288 } 289 prevoff = results->ulr_offset; 290 endsearch = roundup(dp->i_size, dirblksiz); 291 enduseful = 0; 292 293 searchloop: 294 while (results->ulr_offset < endsearch) { 295 if (curcpu()->ci_schedstate.spc_flags & SPCF_SHOULDYIELD) 296 preempt(); 297 /* 298 * If necessary, get the next directory block. 299 */ 300 if ((results->ulr_offset & bmask) == 0) { 301 if (bp != NULL) 302 brelse(bp, 0); 303 error = ulfs_blkatoff(vdp, (off_t)results->ulr_offset, 304 NULL, &bp, false); 305 if (error) 306 goto out; 307 entryoffsetinblock = 0; 308 } 309 /* 310 * If still looking for a slot, and at a DIRBLKSIZ 311 * boundary, have to start looking for free space again. 312 */ 313 if (slotstatus == NONE && 314 (entryoffsetinblock & (dirblksiz - 1)) == 0) { 315 slotoffset = -1; 316 slotfreespace = 0; 317 } 318 /* 319 * Get pointer to next entry. 320 * Full validation checks are slow, so we only check 321 * enough to insure forward progress through the 322 * directory. Complete checks can be run by patching 323 * "lfs_dirchk" to be true. 324 */ 325 KASSERT(bp != NULL); 326 ep = (LFS_DIRHEADER *)((char *)bp->b_data + entryoffsetinblock); 327 if (lfs_dir_getreclen(fs, ep) == 0 || 328 (lfs_dirchk && ulfs_dirbadentry(vdp, ep, entryoffsetinblock))) { 329 int i; 330 331 ulfs_dirbad(dp, results->ulr_offset, "mangled entry"); 332 i = dirblksiz - (entryoffsetinblock & (dirblksiz - 1)); 333 results->ulr_offset += i; 334 entryoffsetinblock += i; 335 continue; 336 } 337 338 /* 339 * If an appropriate sized slot has not yet been found, 340 * check to see if one is available. Also accumulate space 341 * in the current block so that we can determine if 342 * compaction is viable. 343 */ 344 if (slotstatus != FOUND) { 345 int size = lfs_dir_getreclen(fs, ep); 346 347 if (lfs_dir_getino(fs, ep) != 0) 348 size -= LFS_DIRSIZ(fs, ep); 349 if (size > 0) { 350 if (size >= slotneeded) { 351 slotstatus = FOUND; 352 slotoffset = results->ulr_offset; 353 slotsize = lfs_dir_getreclen(fs, ep); 354 } else if (slotstatus == NONE) { 355 slotfreespace += size; 356 if (slotoffset == -1) 357 slotoffset = results->ulr_offset; 358 if (slotfreespace >= slotneeded) { 359 slotstatus = COMPACT; 360 slotsize = results->ulr_offset + 361 lfs_dir_getreclen(fs, ep) - 362 slotoffset; 363 } 364 } 365 } 366 } 367 368 /* 369 * Check for a name match. 370 */ 371 if (lfs_dir_getino(fs, ep)) { 372 int namlen; 373 374 namlen = lfs_dir_getnamlen(fs, ep); 375 if (namlen == cnp->cn_namelen && 376 !memcmp(cnp->cn_nameptr, lfs_dir_nameptr(fs, ep), 377 (unsigned)namlen)) { 378 #ifdef LFS_DIRHASH 379 foundentry: 380 #endif 381 /* 382 * Save directory entry's inode number and 383 * reclen, and release directory buffer. 384 */ 385 if (!FSFMT(vdp) && lfs_dir_gettype(fs, ep) == LFS_DT_WHT) { 386 slotstatus = FOUND; 387 slotoffset = results->ulr_offset; 388 slotsize = lfs_dir_getreclen(fs, ep); 389 results->ulr_reclen = slotsize; 390 /* 391 * This is used to set 392 * results->ulr_endoff, 393 * which may be used by ulfs_direnter() 394 * as a length to truncate the 395 * directory to. Therefore, it must 396 * point past the end of the last 397 * non-empty directory entry. We don't 398 * know where that is in this case, so 399 * we effectively disable shrinking by 400 * using the existing size of the 401 * directory. 402 * 403 * Note that we wouldn't expect to 404 * shrink the directory while rewriting 405 * an existing entry anyway. 406 */ 407 enduseful = endsearch; 408 cnp->cn_flags |= ISWHITEOUT; 409 numdirpasses--; 410 goto notfound; 411 } 412 foundino = lfs_dir_getino(fs, ep); 413 results->ulr_reclen = lfs_dir_getreclen(fs, ep); 414 goto found; 415 } 416 } 417 prevoff = results->ulr_offset; 418 results->ulr_offset += lfs_dir_getreclen(fs, ep); 419 entryoffsetinblock += lfs_dir_getreclen(fs, ep); 420 if (lfs_dir_getino(fs, ep)) 421 enduseful = results->ulr_offset; 422 } 423 notfound: 424 /* 425 * If we started in the middle of the directory and failed 426 * to find our target, we must check the beginning as well. 427 */ 428 if (numdirpasses == 2) { 429 numdirpasses--; 430 results->ulr_offset = 0; 431 endsearch = results->ulr_diroff; 432 goto searchloop; 433 } 434 if (bp != NULL) 435 brelse(bp, 0); 436 /* 437 * If creating, and at end of pathname and current 438 * directory has not been removed, then can consider 439 * allowing file to be created. 440 */ 441 if ((nameiop == CREATE || nameiop == RENAME || 442 (nameiop == DELETE && 443 (cnp->cn_flags & DOWHITEOUT) && 444 (cnp->cn_flags & ISWHITEOUT))) && 445 (flags & ISLASTCN) && dp->i_nlink != 0) { 446 /* 447 * Access for write is interpreted as allowing 448 * creation of files in the directory. 449 */ 450 error = VOP_ACCESS(vdp, VWRITE, cred); 451 if (error) 452 goto out; 453 /* 454 * Return an indication of where the new directory 455 * entry should be put. If we didn't find a slot, 456 * then set results->ulr_count to 0 indicating 457 * that the new slot belongs at the end of the 458 * directory. If we found a slot, then the new entry 459 * can be put in the range from results->ulr_offset to 460 * results->ulr_offset + results->ulr_count. 461 */ 462 if (slotstatus == NONE) { 463 results->ulr_offset = roundup(dp->i_size, dirblksiz); 464 results->ulr_count = 0; 465 enduseful = results->ulr_offset; 466 } else if (nameiop == DELETE) { 467 results->ulr_offset = slotoffset; 468 if ((results->ulr_offset & (dirblksiz - 1)) == 0) 469 results->ulr_count = 0; 470 else 471 results->ulr_count = 472 results->ulr_offset - prevoff; 473 } else { 474 results->ulr_offset = slotoffset; 475 results->ulr_count = slotsize; 476 if (enduseful < slotoffset + slotsize) 477 enduseful = slotoffset + slotsize; 478 } 479 results->ulr_endoff = roundup(enduseful, dirblksiz); 480 #if 0 /* commented out by dbj. none of the on disk fields changed */ 481 dp->i_state |= IN_CHANGE | IN_UPDATE; 482 #endif 483 /* 484 * We return with the directory locked, so that 485 * the parameters we set up above will still be 486 * valid if we actually decide to do a direnter(). 487 * We return ni_vp == NULL to indicate that the entry 488 * does not currently exist; we leave a pointer to 489 * the (locked) directory inode in ndp->ni_dvp. 490 * 491 * NB - if the directory is unlocked, then this 492 * information cannot be used. 493 */ 494 error = EJUSTRETURN; 495 goto out; 496 } 497 /* 498 * Insert name into cache (as non-existent) if appropriate. 499 */ 500 if (nameiop != CREATE) { 501 cache_enter(vdp, *vpp, cnp->cn_nameptr, cnp->cn_namelen, 502 cnp->cn_flags); 503 } 504 error = ENOENT; 505 goto out; 506 507 found: 508 if (numdirpasses == 2) 509 namecache_count_pass2(); 510 /* 511 * Check that directory length properly reflects presence 512 * of this entry. 513 */ 514 if (results->ulr_offset + LFS_DIRSIZ(fs, ep) > dp->i_size) { 515 ulfs_dirbad(dp, results->ulr_offset, "i_size too small"); 516 dp->i_size = 517 results->ulr_offset + LFS_DIRSIZ(fs, ep); 518 DIP_ASSIGN(dp, size, dp->i_size); 519 dp->i_state |= IN_CHANGE | IN_UPDATE; 520 } 521 brelse(bp, 0); 522 523 /* 524 * Found component in pathname. 525 * If the final component of path name, save information 526 * in the cache as to where the entry was found. 527 */ 528 if ((flags & ISLASTCN) && nameiop == LOOKUP) 529 results->ulr_diroff = results->ulr_offset &~ (dirblksiz - 1); 530 531 /* 532 * If deleting, and at end of pathname, return 533 * parameters which can be used to remove file. 534 * Lock the inode, being careful with ".". 535 */ 536 if (nameiop == DELETE && (flags & ISLASTCN)) { 537 /* 538 * Return pointer to current entry in results->ulr_offset, 539 * and distance past previous entry (if there 540 * is a previous entry in this block) in results->ulr_count. 541 * Save directory inode pointer in ndp->ni_dvp for dirremove(). 542 */ 543 if ((results->ulr_offset & (dirblksiz - 1)) == 0) 544 results->ulr_count = 0; 545 else 546 results->ulr_count = results->ulr_offset - prevoff; 547 if (dp->i_number == foundino) { 548 vref(vdp); 549 tdp = vdp; 550 } else { 551 error = vcache_get(vdp->v_mount, 552 &foundino, sizeof(foundino), &tdp); 553 if (error) 554 goto out; 555 } 556 /* 557 * Write access to directory required to delete files. 558 */ 559 error = VOP_ACCESS(vdp, VWRITE, cred); 560 if (error) { 561 vrele(tdp); 562 goto out; 563 } 564 /* 565 * If directory is "sticky", then user must own 566 * the directory, or the file in it, else she 567 * may not delete it (unless she's root). This 568 * implements append-only directories. 569 */ 570 if (dp->i_mode & ISVTX) { 571 error = kauth_authorize_vnode(cred, KAUTH_VNODE_DELETE, 572 tdp, vdp, genfs_can_sticky(cred, dp->i_uid, 573 VTOI(tdp)->i_uid)); 574 if (error) { 575 vrele(tdp); 576 error = EPERM; 577 goto out; 578 } 579 } 580 *vpp = tdp; 581 error = 0; 582 goto out; 583 } 584 585 /* 586 * If rewriting (RENAME), return the inode and the 587 * information required to rewrite the present directory 588 * Must get inode of directory entry to verify it's a 589 * regular file, or empty directory. 590 */ 591 if (nameiop == RENAME && (flags & ISLASTCN)) { 592 error = VOP_ACCESS(vdp, VWRITE, cred); 593 if (error) 594 goto out; 595 /* 596 * Careful about locking second inode. 597 * This can only occur if the target is ".". 598 */ 599 if (dp->i_number == foundino) { 600 error = EISDIR; 601 goto out; 602 } 603 error = vcache_get(vdp->v_mount, 604 &foundino, sizeof(foundino), &tdp); 605 if (error) 606 goto out; 607 *vpp = tdp; 608 error = 0; 609 goto out; 610 } 611 612 if (dp->i_number == foundino) { 613 vref(vdp); /* we want ourself, ie "." */ 614 *vpp = vdp; 615 } else { 616 error = vcache_get(vdp->v_mount, 617 &foundino, sizeof(foundino), &tdp); 618 if (error) 619 goto out; 620 *vpp = tdp; 621 } 622 623 /* 624 * Insert name into cache if appropriate. 625 */ 626 cache_enter(vdp, *vpp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_flags); 627 error = 0; 628 629 out: 630 return error; 631 } 632 633 void 634 ulfs_dirbad(struct inode *ip, doff_t offset, const char *how) 635 { 636 struct mount *mp; 637 638 mp = ITOV(ip)->v_mount; 639 printf("%s: bad dir ino %llu at offset %d: %s\n", 640 mp->mnt_stat.f_mntonname, (unsigned long long)ip->i_number, 641 offset, how); 642 if ((mp->mnt_flag & MNT_RDONLY) == 0) 643 panic("bad dir"); 644 } 645 646 /* 647 * Do consistency checking on a directory entry: 648 * record length must be multiple of 4 649 * entry must fit in rest of its DIRBLKSIZ block 650 * record must be large enough to contain entry 651 * name is not longer than LFS_MAXNAMLEN 652 * name must be as long as advertised, and null terminated 653 */ 654 int 655 ulfs_dirbadentry(struct vnode *dp, LFS_DIRHEADER *ep, int entryoffsetinblock) 656 { 657 int i; 658 int namlen; 659 unsigned reclen; 660 struct ulfsmount *ump = VFSTOULFS(dp->v_mount); 661 struct lfs *fs = ump->um_lfs; 662 int dirblksiz = fs->um_dirblksiz; 663 const char *name; 664 665 namlen = lfs_dir_getnamlen(fs, ep); 666 reclen = lfs_dir_getreclen(fs, ep); 667 if ((reclen & 0x3) != 0 || 668 reclen > dirblksiz - (entryoffsetinblock & (dirblksiz - 1)) || 669 reclen < LFS_DIRSIZ(fs, ep) || namlen > LFS_MAXNAMLEN) { 670 /*return (1); */ 671 printf("First bad, reclen=%#x, DIRSIZ=%lu, namlen=%d, " 672 "flags=%#x, entryoffsetinblock=%d, dirblksiz = %d\n", 673 lfs_dir_getreclen(fs, ep), 674 (u_long)LFS_DIRSIZ(fs, ep), 675 namlen, dp->v_mount->mnt_flag, entryoffsetinblock, 676 dirblksiz); 677 goto bad; 678 } 679 if (lfs_dir_getino(fs, ep) == 0) 680 return (0); 681 name = lfs_dir_nameptr(fs, ep); 682 for (i = 0; i < namlen; i++) 683 if (name[i] == '\0') { 684 /*return (1); */ 685 printf("Second bad\n"); 686 goto bad; 687 } 688 if (name[i]) 689 goto bad; 690 return (0); 691 bad: 692 return (1); 693 } 694 695 /* 696 * Assign the contents of directory entry DIRP, on volume FS. 697 * 698 * NAME/NAMLEN is the name, which is not necessarily null terminated. 699 * INUM is the inode number, and DTYPE is the type code (LFS_DT_*). 700 * 701 * Note that these values typically come from: 702 * cnp->cn_nameptr 703 * cnp->cn_namelen 704 * ip->i_number 705 * LFS_IFTODT(ip->i_mode) 706 * 707 * Does not set d_reclen. 708 */ 709 static void 710 ulfs_direntry_assign(struct lfs *fs, LFS_DIRHEADER *dirp, 711 const char *name, size_t namlen, 712 ino_t inum, unsigned dtype) 713 { 714 lfs_dir_setino(fs, dirp, inum); 715 lfs_dir_setnamlen(fs, dirp, namlen); 716 lfs_dir_settype(fs, dirp, dtype); 717 memcpy(lfs_dir_nameptr(fs, dirp), name, namlen); 718 lfs_dir_nameptr(fs, dirp)[namlen] = '\0'; 719 } 720 721 /* 722 * Write a directory entry after a call to namei, using the parameters 723 * that ulfs_lookup left in nameidata and in the ulfs_lookup_results. 724 * 725 * DVP is the directory to be updated. It must be locked. 726 * ULR is the ulfs_lookup_results structure from the final lookup step. 727 * TVP is not used. (XXX: why is it here? remove it) 728 * CNP is the componentname from the final lookup step. 729 * INUM is the inode number to insert into the new directory entry. 730 * DTYPE is the type code (LFS_DT_*) to insert into the new directory entry. 731 * NEWDIRBP is not used and (XXX) should be removed. The previous 732 * comment here said it was used by the now-removed softupdates code. 733 * 734 * The link count of the target inode is *not* incremented; the 735 * caller does that. 736 * 737 * If ulr->ulr_count is 0, ulfs_lookup did not find space to insert the 738 * directory entry. ulr_offset, which is the place to put the entry, 739 * should be on a block boundary (and should be at the end of the 740 * directory AFAIK) and a fresh block is allocated to put the new 741 * directory entry in. 742 * 743 * If ulr->ulr_count is not zero, ulfs_lookup found a slot to insert 744 * the entry into. This slot ranges from ulr_offset to ulr_offset + 745 * ulr_count. However, this slot may already be partially populated 746 * requiring compaction. See notes below. 747 * 748 * Furthermore, if ulr_count is not zero and ulr_endoff is not the 749 * same as i_size, the directory is truncated to size ulr_endoff. 750 */ 751 int 752 ulfs_direnter(struct vnode *dvp, const struct ulfs_lookup_results *ulr, 753 struct vnode *tvp, 754 struct componentname *cnp, ino_t inum, unsigned dtype, 755 struct buf *newdirbp) 756 { 757 kauth_cred_t cr; 758 int newentrysize; 759 struct inode *dp; 760 struct buf *bp; 761 u_int dsize; 762 LFS_DIRHEADER *ep, *nep; 763 int error, ret, lfs_blkoff, loc, spacefree; 764 char *dirbuf; 765 struct timespec ts; 766 struct ulfsmount *ump = VFSTOULFS(dvp->v_mount); 767 struct lfs *fs = ump->um_lfs; 768 int dirblksiz = fs->um_dirblksiz; 769 const char *name; 770 unsigned namlen, reclen; 771 #ifdef LFS_DIRHASH 772 int dohashadd; 773 #endif 774 775 error = 0; 776 name = cnp->cn_nameptr; /* note: not null-terminated */ 777 namlen = cnp->cn_namelen; 778 cr = cnp->cn_cred; 779 780 dp = VTOI(dvp); 781 newentrysize = LFS_DIRECTSIZ(fs, namlen); 782 783 if (ulr->ulr_count == 0) { 784 /* 785 * If ulr_count is 0, then namei could find no 786 * space in the directory. Here, ulr_offset will 787 * be on a directory block boundary and we will write the 788 * new entry into a fresh block. 789 */ 790 if (ulr->ulr_offset & (dirblksiz - 1)) 791 panic("ulfs_direnter: newblk"); 792 if ((error = lfs_balloc(dvp, (off_t)ulr->ulr_offset, dirblksiz, 793 cr, B_CLRBUF | B_SYNC, &bp)) != 0) { 794 return (error); 795 } 796 dp->i_size = ulr->ulr_offset + dirblksiz; 797 DIP_ASSIGN(dp, size, dp->i_size); 798 dp->i_state |= IN_CHANGE | IN_UPDATE; 799 uvm_vnp_setsize(dvp, dp->i_size); 800 lfs_blkoff = ulr->ulr_offset & (ump->um_mountp->mnt_stat.f_iosize - 1); 801 ep = (LFS_DIRHEADER *)((char *)bp->b_data + lfs_blkoff); 802 ulfs_direntry_assign(fs, ep, name, namlen, inum, dtype); 803 lfs_dir_setreclen(fs, ep, dirblksiz); 804 #ifdef LFS_DIRHASH 805 if (dp->i_dirhash != NULL) { 806 ulfsdirhash_newblk(dp, ulr->ulr_offset); 807 ulfsdirhash_add(dp, ep, ulr->ulr_offset); 808 ulfsdirhash_checkblock(dp, (char *)bp->b_data + lfs_blkoff, 809 ulr->ulr_offset); 810 } 811 #endif 812 error = VOP_BWRITE(bp->b_vp, bp); 813 vfs_timestamp(&ts); 814 ret = lfs_update(dvp, &ts, &ts, UPDATE_DIROP); 815 if (error == 0) 816 return (ret); 817 return (error); 818 } 819 820 /* 821 * If ulr_count is non-zero, then namei found space for the new 822 * entry in the range ulr_offset to ulr_offset + ulr_count 823 * in the directory. To use this space, we may have to compact 824 * the entries located there, by copying them together towards the 825 * beginning of the block, leaving the free space in one usable 826 * chunk at the end. 827 */ 828 829 /* 830 * Increase size of directory if entry eats into new space. 831 * This should never push the size past a new multiple of 832 * DIRBLKSIZ. 833 * 834 * N.B. - THIS IS AN ARTIFACT OF 4.2 AND SHOULD NEVER HAPPEN. 835 */ 836 if (ulr->ulr_offset + ulr->ulr_count > dp->i_size) { 837 #ifdef DIAGNOSTIC 838 printf("ulfs_direnter: reached 4.2-only block, " 839 "not supposed to happen\n"); 840 #endif 841 dp->i_size = ulr->ulr_offset + ulr->ulr_count; 842 DIP_ASSIGN(dp, size, dp->i_size); 843 dp->i_state |= IN_CHANGE | IN_UPDATE; 844 } 845 /* 846 * Get the block containing the space for the new directory entry. 847 */ 848 error = ulfs_blkatoff(dvp, (off_t)ulr->ulr_offset, &dirbuf, &bp, true); 849 if (error) { 850 return (error); 851 } 852 /* 853 * Find space for the new entry. In the simple case, the entry at 854 * offset base will have the space. If it does not, then namei 855 * arranged that compacting the region ulr_offset to 856 * ulr_offset + ulr_count would yield the space. 857 */ 858 ep = (LFS_DIRHEADER *)dirbuf; 859 dsize = (lfs_dir_getino(fs, ep) != 0) ? LFS_DIRSIZ(fs, ep) : 0; 860 spacefree = lfs_dir_getreclen(fs, ep) - dsize; 861 for (loc = lfs_dir_getreclen(fs, ep); loc < ulr->ulr_count; ) { 862 nep = (LFS_DIRHEADER *)(dirbuf + loc); 863 864 /* Trim the existing slot (NB: dsize may be zero). */ 865 lfs_dir_setreclen(fs, ep, dsize); 866 ep = LFS_NEXTDIR(fs, ep); 867 868 reclen = lfs_dir_getreclen(fs, nep); 869 loc += reclen; 870 if (lfs_dir_getino(fs, nep) == 0) { 871 /* 872 * A mid-block unused entry. Such entries are 873 * never created by the kernel, but fsck_ffs 874 * can create them (and it doesn't fix them). 875 * 876 * Add up the free space, and initialise the 877 * relocated entry since we don't memcpy it. 878 */ 879 spacefree += reclen; 880 lfs_dir_setino(fs, ep, 0); 881 dsize = 0; 882 continue; 883 } 884 dsize = LFS_DIRSIZ(fs, nep); 885 spacefree += reclen - dsize; 886 #ifdef LFS_DIRHASH 887 if (dp->i_dirhash != NULL) 888 ulfsdirhash_move(dp, nep, 889 ulr->ulr_offset + ((char *)nep - dirbuf), 890 ulr->ulr_offset + ((char *)ep - dirbuf)); 891 #endif 892 memcpy((void *)ep, (void *)nep, dsize); 893 } 894 /* 895 * Here, `ep' points to a directory entry containing `dsize' in-use 896 * bytes followed by `spacefree' unused bytes. If ep->d_ino == 0, 897 * then the entry is completely unused (dsize == 0). The value 898 * of ep->d_reclen is always indeterminate. 899 * 900 * Update the pointer fields in the previous entry (if any), 901 * copy in the new entry, and write out the block. 902 */ 903 if (lfs_dir_getino(fs, ep) == 0 || 904 (lfs_dir_getino(fs, ep) == ULFS_WINO && 905 memcmp(lfs_dir_nameptr(fs, ep), name, namlen) == 0)) { 906 if (spacefree + dsize < newentrysize) 907 panic("ulfs_direnter: compact1"); 908 reclen = spacefree + dsize; 909 #ifdef LFS_DIRHASH 910 dohashadd = (lfs_dir_getino(fs, ep) == 0); 911 #endif 912 } else { 913 if (spacefree < newentrysize) 914 panic("ulfs_direnter: compact2"); 915 reclen = spacefree; 916 lfs_dir_setreclen(fs, ep, dsize); 917 ep = LFS_NEXTDIR(fs, ep); 918 #ifdef LFS_DIRHASH 919 dohashadd = 1; 920 #endif 921 } 922 923 ulfs_direntry_assign(fs, ep, name, namlen, inum, dtype); 924 lfs_dir_setreclen(fs, ep, reclen); 925 #ifdef LFS_DIRHASH 926 if (dp->i_dirhash != NULL && dohashadd) 927 ulfsdirhash_add(dp, ep, ulr->ulr_offset + ((char *)ep - dirbuf)); 928 if (dp->i_dirhash != NULL) 929 ulfsdirhash_checkblock(dp, dirbuf - 930 (ulr->ulr_offset & (dirblksiz - 1)), 931 ulr->ulr_offset & ~(dirblksiz - 1)); 932 #endif 933 error = VOP_BWRITE(bp->b_vp, bp); 934 dp->i_state |= IN_CHANGE | IN_UPDATE; 935 /* 936 * If all went well, and the directory can be shortened, proceed 937 * with the truncation. Note that we have to unlock the inode for 938 * the entry that we just entered, as the truncation may need to 939 * lock other inodes which can lead to deadlock if we also hold a 940 * lock on the newly entered node. 941 */ 942 if (error == 0 && ulr->ulr_endoff && ulr->ulr_endoff < dp->i_size) { 943 #ifdef LFS_DIRHASH 944 if (dp->i_dirhash != NULL) 945 ulfsdirhash_dirtrunc(dp, ulr->ulr_endoff); 946 #endif 947 (void) lfs_truncate(dvp, (off_t)ulr->ulr_endoff, IO_SYNC, cr); 948 } 949 return (error); 950 } 951 952 /* 953 * Remove a directory entry after a call to namei, using the 954 * parameters that ulfs_lookup left in nameidata and in the 955 * ulfs_lookup_results. 956 * 957 * DVP is the directory to be updated. It must be locked. 958 * ULR is the ulfs_lookup_results structure from the final lookup step. 959 * IP, if not null, is the inode being unlinked. 960 * FLAGS may contain DOWHITEOUT. 961 * ISRMDIR is not used and (XXX) should be removed. 962 * 963 * If FLAGS contains DOWHITEOUT the entry is replaced with a whiteout 964 * instead of being cleared. 965 * 966 * ulr->ulr_offset contains the position of the directory entry 967 * to be removed. 968 * 969 * ulr->ulr_reclen contains the size of the directory entry to be 970 * removed. 971 * 972 * ulr->ulr_count contains the size of the *previous* directory 973 * entry. This allows finding it, for free space management. If 974 * ulr_count is 0, the target entry is at the beginning of the 975 * directory. (Does this ever happen? The first entry should be ".", 976 * which should only be removed at rmdir time. Does rmdir come here 977 * to clear out the "." and ".." entries? Perhaps, but I doubt it.) 978 * 979 * The space is marked free by adding it to the record length (not 980 * name length) of the preceding entry. If the first entry becomes 981 * free, it is marked free by setting the inode number to 0. 982 * 983 * The link count of IP is decremented. Note that this is not the 984 * inverse behavior of ulfs_direnter, which does not adjust link 985 * counts. Sigh. 986 */ 987 int 988 ulfs_dirremove(struct vnode *dvp, const struct ulfs_lookup_results *ulr, 989 struct inode *ip, int flags, int isrmdir) 990 { 991 struct inode *dp = VTOI(dvp); 992 struct lfs *fs = dp->i_lfs; 993 LFS_DIRHEADER *ep; 994 struct buf *bp; 995 int error; 996 997 if (flags & DOWHITEOUT) { 998 /* 999 * Whiteout entry: set d_ino to ULFS_WINO. 1000 */ 1001 error = ulfs_blkatoff(dvp, (off_t)ulr->ulr_offset, (void *)&ep, 1002 &bp, true); 1003 if (error) 1004 return (error); 1005 lfs_dir_setino(fs, ep, ULFS_WINO); 1006 lfs_dir_settype(fs, ep, LFS_DT_WHT); 1007 goto out; 1008 } 1009 1010 if ((error = ulfs_blkatoff(dvp, 1011 (off_t)(ulr->ulr_offset - ulr->ulr_count), (void *)&ep, &bp, true)) != 0) 1012 return (error); 1013 1014 #ifdef LFS_DIRHASH 1015 /* 1016 * Remove the dirhash entry. This is complicated by the fact 1017 * that `ep' is the previous entry when ulr_count != 0. 1018 */ 1019 if (dp->i_dirhash != NULL) 1020 ulfsdirhash_remove(dp, (ulr->ulr_count == 0) ? ep : 1021 LFS_NEXTDIR(fs, ep), ulr->ulr_offset); 1022 #endif 1023 1024 if (ulr->ulr_count == 0) { 1025 /* 1026 * First entry in block: set d_ino to zero. 1027 */ 1028 lfs_dir_setino(fs, ep, 0); 1029 } else { 1030 /* 1031 * Collapse new free space into previous entry. 1032 */ 1033 lfs_dir_setreclen(fs, ep, 1034 lfs_dir_getreclen(fs, ep) + ulr->ulr_reclen); 1035 } 1036 1037 #ifdef LFS_DIRHASH 1038 if (dp->i_dirhash != NULL) { 1039 int dirblksiz = ip->i_lfs->um_dirblksiz; 1040 ulfsdirhash_checkblock(dp, (char *)ep - 1041 ((ulr->ulr_offset - ulr->ulr_count) & (dirblksiz - 1)), 1042 ulr->ulr_offset & ~(dirblksiz - 1)); 1043 } 1044 #endif 1045 1046 out: 1047 if (ip) { 1048 ip->i_nlink--; 1049 DIP_ASSIGN(ip, nlink, ip->i_nlink); 1050 ip->i_state |= IN_CHANGE; 1051 } 1052 /* 1053 * XXX did it ever occur to anyone that it might be a good 1054 * idea to restore ip->i_nlink if this fails? Or something? 1055 * Currently on error return from this function the state of 1056 * ip->i_nlink depends on what happened, and callers 1057 * definitely do not take this into account. 1058 */ 1059 error = VOP_BWRITE(bp->b_vp, bp); 1060 dp->i_state |= IN_CHANGE | IN_UPDATE; 1061 /* 1062 * If the last named reference to a snapshot goes away, 1063 * drop its snapshot reference so that it will be reclaimed 1064 * when last open reference goes away. 1065 */ 1066 if (ip != 0 && (ip->i_flags & SF_SNAPSHOT) != 0 && 1067 ip->i_nlink == 0) 1068 ulfs_snapgone(ip); 1069 return (error); 1070 } 1071 1072 /* 1073 * Rewrite an existing directory entry to point at the inode supplied. 1074 * 1075 * DP is the directory to update. 1076 * OFFSET is the position of the entry in question. It may come 1077 * from ulr_offset of a ulfs_lookup_results. 1078 * OIP is the old inode the directory previously pointed to. 1079 * NEWINUM is the number of the new inode. 1080 * NEWTYPE is the new value for the type field of the directory entry. 1081 * (This is ignored if the fs doesn't support that.) 1082 * ISRMDIR is not used and (XXX) should be removed. 1083 * IFLAGS are added to DP's inode flags. 1084 * 1085 * The link count of OIP is decremented. Note that the link count of 1086 * the new inode is *not* incremented. Yay for symmetry. 1087 */ 1088 int 1089 ulfs_dirrewrite(struct inode *dp, off_t offset, 1090 struct inode *oip, ino_t newinum, int newtype, 1091 int isrmdir, int iflags) 1092 { 1093 struct lfs *fs = dp->i_lfs; 1094 struct buf *bp; 1095 LFS_DIRHEADER *ep; 1096 struct vnode *vdp = ITOV(dp); 1097 int error; 1098 1099 error = ulfs_blkatoff(vdp, offset, (void *)&ep, &bp, true); 1100 if (error) 1101 return (error); 1102 lfs_dir_setino(fs, ep, newinum); 1103 lfs_dir_settype(fs, ep, newtype); 1104 oip->i_nlink--; 1105 DIP_ASSIGN(oip, nlink, oip->i_nlink); 1106 oip->i_state |= IN_CHANGE; 1107 error = VOP_BWRITE(bp->b_vp, bp); 1108 dp->i_state |= iflags; 1109 /* 1110 * If the last named reference to a snapshot goes away, 1111 * drop its snapshot reference so that it will be reclaimed 1112 * when last open reference goes away. 1113 */ 1114 if ((oip->i_flags & SF_SNAPSHOT) != 0 && oip->i_nlink == 0) 1115 ulfs_snapgone(oip); 1116 return (error); 1117 } 1118 1119 /* 1120 * Check if a directory is empty or not. 1121 * Inode supplied must be locked. 1122 * 1123 * Using a struct lfs_dirtemplate here is not precisely 1124 * what we want, but better than using a struct lfs_direct. 1125 * 1126 * NB: does not handle corrupted directories. 1127 */ 1128 int 1129 ulfs_dirempty(struct inode *ip, ino_t parentino, kauth_cred_t cred) 1130 { 1131 struct lfs *fs = ip->i_lfs; 1132 doff_t off; 1133 union lfs_dirtemplate dbuf; 1134 LFS_DIRHEADER *dp = (LFS_DIRHEADER *)&dbuf; 1135 int error, namlen; 1136 const char *name; 1137 size_t count; 1138 /* XXX this should probably use LFS_DIRECTSIZ(fs, 2) */ 1139 #define MINDIRSIZ (sizeof (struct lfs_dirtemplate64) / 2) 1140 1141 for (off = 0; off < ip->i_size; off += lfs_dir_getreclen(fs, dp)) { 1142 error = ulfs_bufio(UIO_READ, ITOV(ip), (void *)dp, MINDIRSIZ, 1143 off, IO_NODELOCKED, cred, &count, NULL); 1144 /* 1145 * Since we read MINDIRSIZ, residual must 1146 * be 0 unless we're at end of file. 1147 */ 1148 if (error || count != 0) 1149 return (0); 1150 /* avoid infinite loops */ 1151 if (lfs_dir_getreclen(fs, dp) == 0) 1152 return (0); 1153 /* skip empty entries */ 1154 if (lfs_dir_getino(fs, dp) == 0 || 1155 lfs_dir_getino(fs, dp) == ULFS_WINO) 1156 continue; 1157 /* accept only "." and ".." */ 1158 namlen = lfs_dir_getnamlen(fs, dp); 1159 name = lfs_dir_nameptr(fs, dp); 1160 if (namlen > 2) 1161 return (0); 1162 if (name[0] != '.') 1163 return (0); 1164 /* 1165 * At this point namlen must be 1 or 2. 1166 * 1 implies ".", 2 implies ".." if second 1167 * char is also "." 1168 */ 1169 if (namlen == 1 && lfs_dir_getino(fs, dp) == ip->i_number) 1170 continue; 1171 if (name[1] == '.' && lfs_dir_getino(fs, dp) == parentino) 1172 continue; 1173 return (0); 1174 } 1175 return (1); 1176 } 1177 1178 #define ULFS_DIRRABLKS 0 1179 int ulfs_dirrablks = ULFS_DIRRABLKS; 1180 1181 /* 1182 * ulfs_blkatoff: Return buffer with the contents of block "offset" from 1183 * the beginning of directory "vp". If "res" is non-NULL, fill it in with 1184 * a pointer to the remaining space in the directory. If the caller intends 1185 * to modify the buffer returned, "modify" must be true. 1186 */ 1187 1188 int 1189 ulfs_blkatoff(struct vnode *vp, off_t offset, char **res, struct buf **bpp, 1190 bool modify) 1191 { 1192 struct inode *ip __diagused; 1193 struct buf *bp; 1194 daddr_t lbn; 1195 const int dirrablks = ulfs_dirrablks; 1196 daddr_t *blks; 1197 int *blksizes; 1198 int run, error; 1199 struct mount *mp = vp->v_mount; 1200 const int bshift = mp->mnt_fs_bshift; 1201 const int bsize = 1 << bshift; 1202 off_t eof; 1203 1204 blks = kmem_alloc((1 + dirrablks) * sizeof(daddr_t), KM_SLEEP); 1205 blksizes = kmem_alloc((1 + dirrablks) * sizeof(int), KM_SLEEP); 1206 ip = VTOI(vp); 1207 KASSERT(vp->v_size == ip->i_size); 1208 GOP_SIZE(vp, vp->v_size, &eof, 0); 1209 lbn = offset >> bshift; 1210 1211 for (run = 0; run <= dirrablks;) { 1212 const off_t curoff = lbn << bshift; 1213 const int size = MIN(eof - curoff, bsize); 1214 1215 if (size == 0) { 1216 break; 1217 } 1218 KASSERT(curoff < eof); 1219 blks[run] = lbn; 1220 blksizes[run] = size; 1221 lbn++; 1222 run++; 1223 if (size != bsize) { 1224 break; 1225 } 1226 } 1227 KASSERT(run >= 1); 1228 error = breadn(vp, blks[0], blksizes[0], &blks[1], &blksizes[1], 1229 run - 1, (modify ? B_MODIFY : 0), &bp); 1230 if (error != 0) { 1231 *bpp = NULL; 1232 goto out; 1233 } 1234 if (res) { 1235 *res = (char *)bp->b_data + (offset & (bsize - 1)); 1236 } 1237 *bpp = bp; 1238 1239 out: 1240 kmem_free(blks, (1 + dirrablks) * sizeof(daddr_t)); 1241 kmem_free(blksizes, (1 + dirrablks) * sizeof(int)); 1242 return error; 1243 } 1244