1 /* $NetBSD: lfs_alloc.c,v 1.131 2015/10/10 22:34:33 dholland Exp $ */ 2 3 /*- 4 * Copyright (c) 1999, 2000, 2001, 2002, 2003, 2007 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Konrad E. Schroder <perseant@hhhh.org>. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 /* 32 * Copyright (c) 1991, 1993 33 * The Regents of the University of California. All rights reserved. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions 37 * are met: 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 3. Neither the name of the University nor the names of its contributors 44 * may be used to endorse or promote products derived from this software 45 * without specific prior written permission. 46 * 47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 57 * SUCH DAMAGE. 58 * 59 * @(#)lfs_alloc.c 8.4 (Berkeley) 1/4/94 60 */ 61 62 #include <sys/cdefs.h> 63 __KERNEL_RCSID(0, "$NetBSD: lfs_alloc.c,v 1.131 2015/10/10 22:34:33 dholland Exp $"); 64 65 #if defined(_KERNEL_OPT) 66 #include "opt_quota.h" 67 #endif 68 69 #include <sys/param.h> 70 #include <sys/systm.h> 71 #include <sys/kernel.h> 72 #include <sys/buf.h> 73 #include <sys/lock.h> 74 #include <sys/vnode.h> 75 #include <sys/syslog.h> 76 #include <sys/mount.h> 77 #include <sys/malloc.h> 78 #include <sys/pool.h> 79 #include <sys/proc.h> 80 #include <sys/tree.h> 81 #include <sys/kauth.h> 82 83 #include <ufs/lfs/ulfs_quotacommon.h> 84 #include <ufs/lfs/ulfs_inode.h> 85 #include <ufs/lfs/ulfsmount.h> 86 #include <ufs/lfs/ulfs_extern.h> 87 88 #include <ufs/lfs/lfs.h> 89 #include <ufs/lfs/lfs_accessors.h> 90 #include <ufs/lfs/lfs_extern.h> 91 #include <ufs/lfs/lfs_kernel.h> 92 93 /* Constants for inode free bitmap */ 94 #define BMSHIFT 5 /* 2 ** 5 = 32 */ 95 #define BMMASK ((1 << BMSHIFT) - 1) 96 #define SET_BITMAP_FREE(F, I) do { \ 97 DLOG((DLOG_ALLOC, "lfs: ino %d wrd %d bit %d set\n", (int)(I), \ 98 (int)((I) >> BMSHIFT), (int)((I) & BMMASK))); \ 99 (F)->lfs_ino_bitmap[(I) >> BMSHIFT] |= (1 << ((I) & BMMASK)); \ 100 } while (0) 101 #define CLR_BITMAP_FREE(F, I) do { \ 102 DLOG((DLOG_ALLOC, "lfs: ino %d wrd %d bit %d clr\n", (int)(I), \ 103 (int)((I) >> BMSHIFT), (int)((I) & BMMASK))); \ 104 (F)->lfs_ino_bitmap[(I) >> BMSHIFT] &= ~(1 << ((I) & BMMASK)); \ 105 } while(0) 106 107 #define ISSET_BITMAP_FREE(F, I) \ 108 ((F)->lfs_ino_bitmap[(I) >> BMSHIFT] & (1 << ((I) & BMMASK))) 109 110 /* 111 * Add a new block to the Ifile, to accommodate future file creations. 112 * Called with the segment lock held. 113 */ 114 int 115 lfs_extend_ifile(struct lfs *fs, kauth_cred_t cred) 116 { 117 struct vnode *vp; 118 struct inode *ip; 119 IFILE64 *ifp64; 120 IFILE32 *ifp32; 121 IFILE_V1 *ifp_v1; 122 struct buf *bp, *cbp; 123 int error; 124 daddr_t i, blkno, xmax; 125 ino_t oldlast, maxino; 126 CLEANERINFO *cip; 127 128 ASSERT_SEGLOCK(fs); 129 130 vp = fs->lfs_ivnode; 131 ip = VTOI(vp); 132 blkno = lfs_lblkno(fs, ip->i_size); 133 if ((error = lfs_balloc(vp, ip->i_size, lfs_sb_getbsize(fs), cred, 0, 134 &bp)) != 0) { 135 return (error); 136 } 137 ip->i_size += lfs_sb_getbsize(fs); 138 lfs_dino_setsize(fs, ip->i_din, ip->i_size); 139 uvm_vnp_setsize(vp, ip->i_size); 140 141 maxino = ((ip->i_size >> lfs_sb_getbshift(fs)) - lfs_sb_getcleansz(fs) - 142 lfs_sb_getsegtabsz(fs)) * lfs_sb_getifpb(fs); 143 fs->lfs_ino_bitmap = (lfs_bm_t *) 144 realloc(fs->lfs_ino_bitmap, ((maxino + BMMASK) >> BMSHIFT) * 145 sizeof(lfs_bm_t), M_SEGMENT, M_WAITOK); 146 KASSERT(fs->lfs_ino_bitmap != NULL); 147 148 i = (blkno - lfs_sb_getsegtabsz(fs) - lfs_sb_getcleansz(fs)) * 149 lfs_sb_getifpb(fs); 150 151 /* 152 * We insert the new inodes at the head of the free list. 153 * Under normal circumstances, the free list is empty here, 154 * so we are also incidentally placing them at the end (which 155 * we must do if we are to keep them in order). 156 */ 157 LFS_GET_HEADFREE(fs, cip, cbp, &oldlast); 158 LFS_PUT_HEADFREE(fs, cip, cbp, i); 159 #ifdef DIAGNOSTIC 160 if (lfs_sb_getfreehd(fs) == LFS_UNUSED_INUM) 161 panic("inode 0 allocated [2]"); 162 #endif /* DIAGNOSTIC */ 163 xmax = i + lfs_sb_getifpb(fs); 164 165 if (fs->lfs_is64) { 166 for (ifp64 = (IFILE64 *)bp->b_data; i < xmax; ++ifp64) { 167 SET_BITMAP_FREE(fs, i); 168 ifp64->if_version = 1; 169 ifp64->if_daddr = LFS_UNUSED_DADDR; 170 ifp64->if_nextfree = ++i; 171 } 172 ifp64--; 173 ifp64->if_nextfree = oldlast; 174 } else if (lfs_sb_getversion(fs) > 1) { 175 for (ifp32 = (IFILE32 *)bp->b_data; i < xmax; ++ifp32) { 176 SET_BITMAP_FREE(fs, i); 177 ifp32->if_version = 1; 178 ifp32->if_daddr = LFS_UNUSED_DADDR; 179 ifp32->if_nextfree = ++i; 180 } 181 ifp32--; 182 ifp32->if_nextfree = oldlast; 183 } else { 184 for (ifp_v1 = (IFILE_V1 *)bp->b_data; i < xmax; ++ifp_v1) { 185 SET_BITMAP_FREE(fs, i); 186 ifp_v1->if_version = 1; 187 ifp_v1->if_daddr = LFS_UNUSED_DADDR; 188 ifp_v1->if_nextfree = ++i; 189 } 190 ifp_v1--; 191 ifp_v1->if_nextfree = oldlast; 192 } 193 LFS_PUT_TAILFREE(fs, cip, cbp, xmax - 1); 194 195 (void) LFS_BWRITE_LOG(bp); /* Ifile */ 196 197 return 0; 198 } 199 200 /* Allocate a new inode. */ 201 /* ARGSUSED */ 202 /* VOP_BWRITE 2i times */ 203 int 204 lfs_valloc(struct vnode *pvp, int mode, kauth_cred_t cred, 205 ino_t *ino, int *gen) 206 { 207 struct lfs *fs; 208 struct buf *bp, *cbp; 209 IFILE *ifp; 210 int error; 211 CLEANERINFO *cip; 212 213 fs = VTOI(pvp)->i_lfs; 214 if (fs->lfs_ronly) 215 return EROFS; 216 217 ASSERT_NO_SEGLOCK(fs); 218 219 lfs_seglock(fs, SEGM_PROT); 220 221 /* Get the head of the freelist. */ 222 LFS_GET_HEADFREE(fs, cip, cbp, ino); 223 KASSERT(*ino != LFS_UNUSED_INUM && *ino != LFS_IFILE_INUM); 224 225 DLOG((DLOG_ALLOC, "lfs_valloc: allocate inode %" PRId64 "\n", 226 *ino)); 227 228 /* 229 * Remove the inode from the free list and write the new start 230 * of the free list into the superblock. 231 */ 232 CLR_BITMAP_FREE(fs, *ino); 233 LFS_IENTRY(ifp, fs, *ino, bp); 234 if (lfs_if_getdaddr(fs, ifp) != LFS_UNUSED_DADDR) 235 panic("lfs_valloc: inuse inode %" PRId64 " on the free list", 236 *ino); 237 LFS_PUT_HEADFREE(fs, cip, cbp, lfs_if_getnextfree(fs, ifp)); 238 DLOG((DLOG_ALLOC, "lfs_valloc: headfree %" PRId64 " -> %ju\n", 239 *ino, (uintmax_t)lfs_if_getnextfree(fs, ifp))); 240 241 /* version was updated by vfree */ 242 *gen = lfs_if_getversion(fs, ifp); 243 brelse(bp, 0); 244 245 /* Extend IFILE so that the next lfs_valloc will succeed. */ 246 if (lfs_sb_getfreehd(fs) == LFS_UNUSED_INUM) { 247 if ((error = lfs_extend_ifile(fs, cred)) != 0) { 248 LFS_PUT_HEADFREE(fs, cip, cbp, *ino); 249 lfs_segunlock(fs); 250 return error; 251 } 252 } 253 #ifdef DIAGNOSTIC 254 if (lfs_sb_getfreehd(fs) == LFS_UNUSED_INUM) 255 panic("inode 0 allocated [3]"); 256 #endif /* DIAGNOSTIC */ 257 258 /* Set superblock modified bit and increment file count. */ 259 mutex_enter(&lfs_lock); 260 fs->lfs_fmod = 1; 261 mutex_exit(&lfs_lock); 262 lfs_sb_addnfiles(fs, 1); 263 264 lfs_segunlock(fs); 265 266 return 0; 267 } 268 269 /* 270 * Allocate a new inode with given inode number and version. 271 */ 272 int 273 lfs_valloc_fixed(struct lfs *fs, ino_t ino, int vers) 274 { 275 IFILE *ifp; 276 struct buf *bp, *cbp; 277 ino_t headino, thisino, oldnext; 278 CLEANERINFO *cip; 279 280 /* If the Ifile is too short to contain this inum, extend it */ 281 while (VTOI(fs->lfs_ivnode)->i_size <= (ino / 282 lfs_sb_getifpb(fs) + lfs_sb_getcleansz(fs) + lfs_sb_getsegtabsz(fs)) 283 << lfs_sb_getbshift(fs)) { 284 lfs_extend_ifile(fs, NOCRED); 285 } 286 287 LFS_IENTRY(ifp, fs, ino, bp); 288 oldnext = lfs_if_getnextfree(fs, ifp); 289 lfs_if_setversion(fs, ifp, vers); 290 brelse(bp, 0); 291 292 LFS_GET_HEADFREE(fs, cip, cbp, &headino); 293 if (headino == ino) { 294 LFS_PUT_HEADFREE(fs, cip, cbp, oldnext); 295 } else { 296 ino_t nextfree; 297 298 thisino = headino; 299 while (1) { 300 LFS_IENTRY(ifp, fs, thisino, bp); 301 nextfree = lfs_if_getnextfree(fs, ifp); 302 if (nextfree == ino || 303 nextfree == LFS_UNUSED_INUM) 304 break; 305 thisino = nextfree; 306 brelse(bp, 0); 307 } 308 if (nextfree == LFS_UNUSED_INUM) { 309 brelse(bp, 0); 310 return ENOENT; 311 } 312 lfs_if_setnextfree(fs, ifp, oldnext); 313 LFS_BWRITE_LOG(bp); 314 } 315 316 return 0; 317 } 318 319 #if 0 320 /* 321 * Find the highest-numbered allocated inode. 322 * This will be used to shrink the Ifile. 323 */ 324 static inline ino_t 325 lfs_last_alloc_ino(struct lfs *fs) 326 { 327 ino_t ino, maxino; 328 329 maxino = ((fs->lfs_ivnode->v_size >> lfs_sb_getbshift(fs)) - 330 lfs_sb_getcleansz(fs) - lfs_sb_getsegtabsz(fs)) * 331 lfs_sb_getifpb(fs); 332 for (ino = maxino - 1; ino > LFS_UNUSED_INUM; --ino) { 333 if (ISSET_BITMAP_FREE(fs, ino) == 0) 334 break; 335 } 336 return ino; 337 } 338 #endif 339 340 /* 341 * Find the previous (next lowest numbered) free inode, if any. 342 * If there is none, return LFS_UNUSED_INUM. 343 */ 344 static inline ino_t 345 lfs_freelist_prev(struct lfs *fs, ino_t ino) 346 { 347 ino_t tino, bound, bb, freehdbb; 348 349 if (lfs_sb_getfreehd(fs) == LFS_UNUSED_INUM) /* No free inodes at all */ 350 return LFS_UNUSED_INUM; 351 352 /* Search our own word first */ 353 bound = ino & ~BMMASK; 354 for (tino = ino - 1; tino >= bound && tino > LFS_UNUSED_INUM; tino--) 355 if (ISSET_BITMAP_FREE(fs, tino)) 356 return tino; 357 /* If there are no lower words to search, just return */ 358 if (ino >> BMSHIFT == 0) 359 return LFS_UNUSED_INUM; 360 361 /* 362 * Find a word with a free inode in it. We have to be a bit 363 * careful here since ino_t is unsigned. 364 */ 365 freehdbb = (lfs_sb_getfreehd(fs) >> BMSHIFT); 366 for (bb = (ino >> BMSHIFT) - 1; bb >= freehdbb && bb > 0; --bb) 367 if (fs->lfs_ino_bitmap[bb]) 368 break; 369 if (fs->lfs_ino_bitmap[bb] == 0) 370 return LFS_UNUSED_INUM; 371 372 /* Search the word we found */ 373 for (tino = (bb << BMSHIFT) | BMMASK; tino >= (bb << BMSHIFT) && 374 tino > LFS_UNUSED_INUM; tino--) 375 if (ISSET_BITMAP_FREE(fs, tino)) 376 break; 377 378 if (tino <= LFS_IFILE_INUM) 379 tino = LFS_UNUSED_INUM; 380 381 return tino; 382 } 383 384 /* Free an inode. */ 385 /* ARGUSED */ 386 /* VOP_BWRITE 2i times */ 387 int 388 lfs_vfree(struct vnode *vp, ino_t ino, int mode) 389 { 390 SEGUSE *sup; 391 CLEANERINFO *cip; 392 struct buf *cbp, *bp; 393 IFILE *ifp; 394 struct inode *ip; 395 struct lfs *fs; 396 daddr_t old_iaddr; 397 ino_t otail; 398 399 /* Get the inode number and file system. */ 400 ip = VTOI(vp); 401 fs = ip->i_lfs; 402 ino = ip->i_number; 403 404 ASSERT_NO_SEGLOCK(fs); 405 DLOG((DLOG_ALLOC, "lfs_vfree: free ino %lld\n", (long long)ino)); 406 407 /* Drain of pending writes */ 408 mutex_enter(vp->v_interlock); 409 while (lfs_sb_getversion(fs) > 1 && WRITEINPROG(vp)) { 410 cv_wait(&vp->v_cv, vp->v_interlock); 411 } 412 mutex_exit(vp->v_interlock); 413 414 lfs_seglock(fs, SEGM_PROT); 415 416 lfs_unmark_vnode(vp); 417 mutex_enter(&lfs_lock); 418 if (vp->v_uflag & VU_DIROP) { 419 vp->v_uflag &= ~VU_DIROP; 420 --lfs_dirvcount; 421 --fs->lfs_dirvcount; 422 TAILQ_REMOVE(&fs->lfs_dchainhd, ip, i_lfs_dchain); 423 wakeup(&fs->lfs_dirvcount); 424 wakeup(&lfs_dirvcount); 425 mutex_exit(&lfs_lock); 426 vrele(vp); 427 428 /* 429 * If this inode is not going to be written any more, any 430 * segment accounting left over from its truncation needs 431 * to occur at the end of the next dirops flush. Attach 432 * them to the fs-wide list for that purpose. 433 */ 434 if (LIST_FIRST(&ip->i_lfs_segdhd) != NULL) { 435 struct segdelta *sd; 436 437 while((sd = LIST_FIRST(&ip->i_lfs_segdhd)) != NULL) { 438 LIST_REMOVE(sd, list); 439 LIST_INSERT_HEAD(&fs->lfs_segdhd, sd, list); 440 } 441 } 442 } else { 443 /* 444 * If it's not a dirop, we can finalize right away. 445 */ 446 mutex_exit(&lfs_lock); 447 lfs_finalize_ino_seguse(fs, ip); 448 } 449 450 mutex_enter(&lfs_lock); 451 LFS_CLR_UINO(ip, IN_ACCESSED|IN_CLEANING|IN_MODIFIED); 452 mutex_exit(&lfs_lock); 453 ip->i_flag &= ~IN_ALLMOD; 454 ip->i_lfs_iflags |= LFSI_DELETED; 455 456 /* 457 * Set the ifile's inode entry to unused, increment its version number 458 * and link it onto the free chain. 459 */ 460 SET_BITMAP_FREE(fs, ino); 461 LFS_IENTRY(ifp, fs, ino, bp); 462 old_iaddr = lfs_if_getdaddr(fs, ifp); 463 lfs_if_setdaddr(fs, ifp, LFS_UNUSED_DADDR); 464 lfs_if_setversion(fs, ifp, lfs_if_getversion(fs, ifp) + 1); 465 if (lfs_sb_getversion(fs) == 1) { 466 ino_t nextfree; 467 468 LFS_GET_HEADFREE(fs, cip, cbp, &nextfree); 469 lfs_if_setnextfree(fs, ifp, nextfree); 470 LFS_PUT_HEADFREE(fs, cip, cbp, ino); 471 (void) LFS_BWRITE_LOG(bp); /* Ifile */ 472 } else { 473 ino_t tino, onf; 474 475 lfs_if_setnextfree(fs, ifp, LFS_UNUSED_INUM); 476 (void) LFS_BWRITE_LOG(bp); /* Ifile */ 477 478 tino = lfs_freelist_prev(fs, ino); 479 if (tino == LFS_UNUSED_INUM) { 480 ino_t nextfree; 481 482 /* Nothing free below us, put us on the head */ 483 LFS_IENTRY(ifp, fs, ino, bp); 484 LFS_GET_HEADFREE(fs, cip, cbp, &nextfree); 485 lfs_if_setnextfree(fs, ifp, nextfree); 486 LFS_PUT_HEADFREE(fs, cip, cbp, ino); 487 DLOG((DLOG_ALLOC, "lfs_vfree: headfree %lld -> %lld\n", 488 (long long)nextfree, (long long)ino)); 489 LFS_BWRITE_LOG(bp); /* Ifile */ 490 491 /* If the list was empty, set tail too */ 492 LFS_GET_TAILFREE(fs, cip, cbp, &otail); 493 if (otail == LFS_UNUSED_INUM) { 494 LFS_PUT_TAILFREE(fs, cip, cbp, ino); 495 DLOG((DLOG_ALLOC, "lfs_vfree: tailfree %lld " 496 "-> %lld\n", (long long)otail, 497 (long long)ino)); 498 } 499 } else { 500 /* 501 * Insert this inode into the list after tino. 502 * We hold the segment lock so we don't have to 503 * worry about blocks being written out of order. 504 */ 505 DLOG((DLOG_ALLOC, "lfs_vfree: insert ino %lld " 506 " after %lld\n", ino, tino)); 507 508 LFS_IENTRY(ifp, fs, tino, bp); 509 onf = lfs_if_getnextfree(fs, ifp); 510 lfs_if_setnextfree(fs, ifp, ino); 511 LFS_BWRITE_LOG(bp); /* Ifile */ 512 513 LFS_IENTRY(ifp, fs, ino, bp); 514 lfs_if_setnextfree(fs, ifp, onf); 515 LFS_BWRITE_LOG(bp); /* Ifile */ 516 517 /* If we're last, put us on the tail */ 518 if (onf == LFS_UNUSED_INUM) { 519 LFS_GET_TAILFREE(fs, cip, cbp, &otail); 520 LFS_PUT_TAILFREE(fs, cip, cbp, ino); 521 DLOG((DLOG_ALLOC, "lfs_vfree: tailfree %lld " 522 "-> %lld\n", (long long)otail, 523 (long long)ino)); 524 } 525 } 526 } 527 #ifdef DIAGNOSTIC 528 if (ino == LFS_UNUSED_INUM) { 529 panic("inode 0 freed"); 530 } 531 #endif /* DIAGNOSTIC */ 532 if (old_iaddr != LFS_UNUSED_DADDR) { 533 LFS_SEGENTRY(sup, fs, lfs_dtosn(fs, old_iaddr), bp); 534 #ifdef DIAGNOSTIC 535 if (sup->su_nbytes < DINOSIZE(fs)) { 536 printf("lfs_vfree: negative byte count" 537 " (segment %" PRIu32 " short by %d)\n", 538 lfs_dtosn(fs, old_iaddr), 539 (int)DINOSIZE(fs) - 540 sup->su_nbytes); 541 panic("lfs_vfree: negative byte count"); 542 sup->su_nbytes = DINOSIZE(fs); 543 } 544 #endif 545 sup->su_nbytes -= DINOSIZE(fs); 546 LFS_WRITESEGENTRY(sup, fs, lfs_dtosn(fs, old_iaddr), bp); /* Ifile */ 547 } 548 549 /* Set superblock modified bit and decrement file count. */ 550 mutex_enter(&lfs_lock); 551 fs->lfs_fmod = 1; 552 mutex_exit(&lfs_lock); 553 lfs_sb_subnfiles(fs, 1); 554 555 lfs_segunlock(fs); 556 557 return (0); 558 } 559 560 /* 561 * Sort the freelist and set up the free-inode bitmap. 562 * To be called by lfs_mountfs(). 563 */ 564 void 565 lfs_order_freelist(struct lfs *fs) 566 { 567 CLEANERINFO *cip; 568 IFILE *ifp = NULL; 569 struct buf *bp; 570 ino_t ino, firstino, lastino, maxino; 571 #ifdef notyet 572 struct vnode *vp; 573 #endif 574 575 ASSERT_NO_SEGLOCK(fs); 576 lfs_seglock(fs, SEGM_PROT); 577 578 maxino = ((fs->lfs_ivnode->v_size >> lfs_sb_getbshift(fs)) - 579 lfs_sb_getcleansz(fs) - lfs_sb_getsegtabsz(fs)) * lfs_sb_getifpb(fs); 580 fs->lfs_ino_bitmap = 581 malloc(((maxino + BMMASK) >> BMSHIFT) * sizeof(lfs_bm_t), 582 M_SEGMENT, M_WAITOK | M_ZERO); 583 KASSERT(fs->lfs_ino_bitmap != NULL); 584 585 firstino = lastino = LFS_UNUSED_INUM; 586 for (ino = 0; ino < maxino; ino++) { 587 if (ino % lfs_sb_getifpb(fs) == 0) 588 LFS_IENTRY(ifp, fs, ino, bp); 589 else 590 LFS_IENTRY_NEXT(ifp, fs); 591 592 /* Don't put zero or ifile on the free list */ 593 if (ino == LFS_UNUSED_INUM || ino == LFS_IFILE_INUM) 594 continue; 595 596 #ifdef notyet 597 /* Address orphaned files */ 598 if (lfs_if_getnextfree(fs, ifp) == LFS_ORPHAN_NEXTFREE && 599 VFS_VGET(fs->lfs_ivnode->v_mount, ino, &vp) == 0) { 600 unsigned segno; 601 602 segno = lfs_dtosn(fs, lfs_if_getdaddr(fs, ifp)); 603 lfs_truncate(vp, 0, 0, NOCRED); 604 vput(vp); 605 LFS_SEGENTRY(sup, fs, segno, bp); 606 KASSERT(sup->su_nbytes >= DINOSIZE(fs)); 607 sup->su_nbytes -= DINOSIZE(fs); 608 LFS_WRITESEGENTRY(sup, fs, segno, bp); 609 610 /* Set up to fall through to next section */ 611 lfs_if_setdaddr(fs, ifp, LFS_UNUSED_DADDR); 612 LFS_BWRITE_LOG(bp); 613 LFS_IENTRY(ifp, fs, ino, bp); 614 } 615 #endif 616 617 if (lfs_if_getdaddr(fs, ifp) == LFS_UNUSED_DADDR) { 618 if (firstino == LFS_UNUSED_INUM) 619 firstino = ino; 620 else { 621 brelse(bp, 0); 622 623 LFS_IENTRY(ifp, fs, lastino, bp); 624 lfs_if_setnextfree(fs, ifp, ino); 625 LFS_BWRITE_LOG(bp); 626 627 LFS_IENTRY(ifp, fs, ino, bp); 628 } 629 lastino = ino; 630 631 SET_BITMAP_FREE(fs, ino); 632 } 633 634 if ((ino + 1) % lfs_sb_getifpb(fs) == 0) 635 brelse(bp, 0); 636 } 637 638 LFS_PUT_HEADFREE(fs, cip, bp, firstino); 639 LFS_PUT_TAILFREE(fs, cip, bp, lastino); 640 641 lfs_segunlock(fs); 642 } 643 644 void 645 lfs_orphan(struct lfs *fs, ino_t ino) 646 { 647 IFILE *ifp; 648 struct buf *bp; 649 650 LFS_IENTRY(ifp, fs, ino, bp); 651 lfs_if_setnextfree(fs, ifp, LFS_ORPHAN_NEXTFREE); 652 LFS_BWRITE_LOG(bp); 653 } 654