1 /* $NetBSD: lfs_alloc.c,v 1.130 2015/09/13 07:53:37 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.130 2015/09/13 07:53:37 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)) * fs->lfs_ifpb; 331 for (ino = maxino - 1; ino > LFS_UNUSED_INUM; --ino) { 332 if (ISSET_BITMAP_FREE(fs, ino) == 0) 333 break; 334 } 335 return ino; 336 } 337 #endif 338 339 /* 340 * Find the previous (next lowest numbered) free inode, if any. 341 * If there is none, return LFS_UNUSED_INUM. 342 */ 343 static inline ino_t 344 lfs_freelist_prev(struct lfs *fs, ino_t ino) 345 { 346 ino_t tino, bound, bb, freehdbb; 347 348 if (lfs_sb_getfreehd(fs) == LFS_UNUSED_INUM) /* No free inodes at all */ 349 return LFS_UNUSED_INUM; 350 351 /* Search our own word first */ 352 bound = ino & ~BMMASK; 353 for (tino = ino - 1; tino >= bound && tino > LFS_UNUSED_INUM; tino--) 354 if (ISSET_BITMAP_FREE(fs, tino)) 355 return tino; 356 /* If there are no lower words to search, just return */ 357 if (ino >> BMSHIFT == 0) 358 return LFS_UNUSED_INUM; 359 360 /* 361 * Find a word with a free inode in it. We have to be a bit 362 * careful here since ino_t is unsigned. 363 */ 364 freehdbb = (lfs_sb_getfreehd(fs) >> BMSHIFT); 365 for (bb = (ino >> BMSHIFT) - 1; bb >= freehdbb && bb > 0; --bb) 366 if (fs->lfs_ino_bitmap[bb]) 367 break; 368 if (fs->lfs_ino_bitmap[bb] == 0) 369 return LFS_UNUSED_INUM; 370 371 /* Search the word we found */ 372 for (tino = (bb << BMSHIFT) | BMMASK; tino >= (bb << BMSHIFT) && 373 tino > LFS_UNUSED_INUM; tino--) 374 if (ISSET_BITMAP_FREE(fs, tino)) 375 break; 376 377 if (tino <= LFS_IFILE_INUM) 378 tino = LFS_UNUSED_INUM; 379 380 return tino; 381 } 382 383 /* Free an inode. */ 384 /* ARGUSED */ 385 /* VOP_BWRITE 2i times */ 386 int 387 lfs_vfree(struct vnode *vp, ino_t ino, int mode) 388 { 389 SEGUSE *sup; 390 CLEANERINFO *cip; 391 struct buf *cbp, *bp; 392 IFILE *ifp; 393 struct inode *ip; 394 struct lfs *fs; 395 daddr_t old_iaddr; 396 ino_t otail; 397 398 /* Get the inode number and file system. */ 399 ip = VTOI(vp); 400 fs = ip->i_lfs; 401 ino = ip->i_number; 402 403 ASSERT_NO_SEGLOCK(fs); 404 DLOG((DLOG_ALLOC, "lfs_vfree: free ino %lld\n", (long long)ino)); 405 406 /* Drain of pending writes */ 407 mutex_enter(vp->v_interlock); 408 while (lfs_sb_getversion(fs) > 1 && WRITEINPROG(vp)) { 409 cv_wait(&vp->v_cv, vp->v_interlock); 410 } 411 mutex_exit(vp->v_interlock); 412 413 lfs_seglock(fs, SEGM_PROT); 414 415 lfs_unmark_vnode(vp); 416 mutex_enter(&lfs_lock); 417 if (vp->v_uflag & VU_DIROP) { 418 vp->v_uflag &= ~VU_DIROP; 419 --lfs_dirvcount; 420 --fs->lfs_dirvcount; 421 TAILQ_REMOVE(&fs->lfs_dchainhd, ip, i_lfs_dchain); 422 wakeup(&fs->lfs_dirvcount); 423 wakeup(&lfs_dirvcount); 424 mutex_exit(&lfs_lock); 425 vrele(vp); 426 427 /* 428 * If this inode is not going to be written any more, any 429 * segment accounting left over from its truncation needs 430 * to occur at the end of the next dirops flush. Attach 431 * them to the fs-wide list for that purpose. 432 */ 433 if (LIST_FIRST(&ip->i_lfs_segdhd) != NULL) { 434 struct segdelta *sd; 435 436 while((sd = LIST_FIRST(&ip->i_lfs_segdhd)) != NULL) { 437 LIST_REMOVE(sd, list); 438 LIST_INSERT_HEAD(&fs->lfs_segdhd, sd, list); 439 } 440 } 441 } else { 442 /* 443 * If it's not a dirop, we can finalize right away. 444 */ 445 mutex_exit(&lfs_lock); 446 lfs_finalize_ino_seguse(fs, ip); 447 } 448 449 mutex_enter(&lfs_lock); 450 LFS_CLR_UINO(ip, IN_ACCESSED|IN_CLEANING|IN_MODIFIED); 451 mutex_exit(&lfs_lock); 452 ip->i_flag &= ~IN_ALLMOD; 453 ip->i_lfs_iflags |= LFSI_DELETED; 454 455 /* 456 * Set the ifile's inode entry to unused, increment its version number 457 * and link it onto the free chain. 458 */ 459 SET_BITMAP_FREE(fs, ino); 460 LFS_IENTRY(ifp, fs, ino, bp); 461 old_iaddr = lfs_if_getdaddr(fs, ifp); 462 lfs_if_setdaddr(fs, ifp, LFS_UNUSED_DADDR); 463 lfs_if_setversion(fs, ifp, lfs_if_getversion(fs, ifp) + 1); 464 if (lfs_sb_getversion(fs) == 1) { 465 ino_t nextfree; 466 467 LFS_GET_HEADFREE(fs, cip, cbp, &nextfree); 468 lfs_if_setnextfree(fs, ifp, nextfree); 469 LFS_PUT_HEADFREE(fs, cip, cbp, ino); 470 (void) LFS_BWRITE_LOG(bp); /* Ifile */ 471 } else { 472 ino_t tino, onf; 473 474 lfs_if_setnextfree(fs, ifp, LFS_UNUSED_INUM); 475 (void) LFS_BWRITE_LOG(bp); /* Ifile */ 476 477 tino = lfs_freelist_prev(fs, ino); 478 if (tino == LFS_UNUSED_INUM) { 479 ino_t nextfree; 480 481 /* Nothing free below us, put us on the head */ 482 LFS_IENTRY(ifp, fs, ino, bp); 483 LFS_GET_HEADFREE(fs, cip, cbp, &nextfree); 484 lfs_if_setnextfree(fs, ifp, nextfree); 485 LFS_PUT_HEADFREE(fs, cip, cbp, ino); 486 DLOG((DLOG_ALLOC, "lfs_vfree: headfree %lld -> %lld\n", 487 (long long)nextfree, (long long)ino)); 488 LFS_BWRITE_LOG(bp); /* Ifile */ 489 490 /* If the list was empty, set tail too */ 491 LFS_GET_TAILFREE(fs, cip, cbp, &otail); 492 if (otail == LFS_UNUSED_INUM) { 493 LFS_PUT_TAILFREE(fs, cip, cbp, ino); 494 DLOG((DLOG_ALLOC, "lfs_vfree: tailfree %lld " 495 "-> %lld\n", (long long)otail, 496 (long long)ino)); 497 } 498 } else { 499 /* 500 * Insert this inode into the list after tino. 501 * We hold the segment lock so we don't have to 502 * worry about blocks being written out of order. 503 */ 504 DLOG((DLOG_ALLOC, "lfs_vfree: insert ino %lld " 505 " after %lld\n", ino, tino)); 506 507 LFS_IENTRY(ifp, fs, tino, bp); 508 onf = lfs_if_getnextfree(fs, ifp); 509 lfs_if_setnextfree(fs, ifp, ino); 510 LFS_BWRITE_LOG(bp); /* Ifile */ 511 512 LFS_IENTRY(ifp, fs, ino, bp); 513 lfs_if_setnextfree(fs, ifp, onf); 514 LFS_BWRITE_LOG(bp); /* Ifile */ 515 516 /* If we're last, put us on the tail */ 517 if (onf == LFS_UNUSED_INUM) { 518 LFS_GET_TAILFREE(fs, cip, cbp, &otail); 519 LFS_PUT_TAILFREE(fs, cip, cbp, ino); 520 DLOG((DLOG_ALLOC, "lfs_vfree: tailfree %lld " 521 "-> %lld\n", (long long)otail, 522 (long long)ino)); 523 } 524 } 525 } 526 #ifdef DIAGNOSTIC 527 if (ino == LFS_UNUSED_INUM) { 528 panic("inode 0 freed"); 529 } 530 #endif /* DIAGNOSTIC */ 531 if (old_iaddr != LFS_UNUSED_DADDR) { 532 LFS_SEGENTRY(sup, fs, lfs_dtosn(fs, old_iaddr), bp); 533 #ifdef DIAGNOSTIC 534 if (sup->su_nbytes < DINOSIZE(fs)) { 535 printf("lfs_vfree: negative byte count" 536 " (segment %" PRIu32 " short by %d)\n", 537 lfs_dtosn(fs, old_iaddr), 538 (int)DINOSIZE(fs) - 539 sup->su_nbytes); 540 panic("lfs_vfree: negative byte count"); 541 sup->su_nbytes = DINOSIZE(fs); 542 } 543 #endif 544 sup->su_nbytes -= DINOSIZE(fs); 545 LFS_WRITESEGENTRY(sup, fs, lfs_dtosn(fs, old_iaddr), bp); /* Ifile */ 546 } 547 548 /* Set superblock modified bit and decrement file count. */ 549 mutex_enter(&lfs_lock); 550 fs->lfs_fmod = 1; 551 mutex_exit(&lfs_lock); 552 lfs_sb_subnfiles(fs, 1); 553 554 lfs_segunlock(fs); 555 556 return (0); 557 } 558 559 /* 560 * Sort the freelist and set up the free-inode bitmap. 561 * To be called by lfs_mountfs(). 562 */ 563 void 564 lfs_order_freelist(struct lfs *fs) 565 { 566 CLEANERINFO *cip; 567 IFILE *ifp = NULL; 568 struct buf *bp; 569 ino_t ino, firstino, lastino, maxino; 570 #ifdef notyet 571 struct vnode *vp; 572 #endif 573 574 ASSERT_NO_SEGLOCK(fs); 575 lfs_seglock(fs, SEGM_PROT); 576 577 maxino = ((fs->lfs_ivnode->v_size >> lfs_sb_getbshift(fs)) - 578 lfs_sb_getcleansz(fs) - lfs_sb_getsegtabsz(fs)) * lfs_sb_getifpb(fs); 579 fs->lfs_ino_bitmap = 580 malloc(((maxino + BMMASK) >> BMSHIFT) * sizeof(lfs_bm_t), 581 M_SEGMENT, M_WAITOK | M_ZERO); 582 KASSERT(fs->lfs_ino_bitmap != NULL); 583 584 firstino = lastino = LFS_UNUSED_INUM; 585 for (ino = 0; ino < maxino; ino++) { 586 if (ino % lfs_sb_getifpb(fs) == 0) 587 LFS_IENTRY(ifp, fs, ino, bp); 588 else 589 LFS_IENTRY_NEXT(ifp, fs); 590 591 /* Don't put zero or ifile on the free list */ 592 if (ino == LFS_UNUSED_INUM || ino == LFS_IFILE_INUM) 593 continue; 594 595 #ifdef notyet 596 /* Address orphaned files */ 597 if (lfs_if_getnextfree(fs, ifp) == LFS_ORPHAN_NEXTFREE && 598 VFS_VGET(fs->lfs_ivnode->v_mount, ino, &vp) == 0) { 599 unsigned segno; 600 601 segno = lfs_dtosn(fs, lfs_if_getdaddr(fs, ifp)); 602 lfs_truncate(vp, 0, 0, NOCRED); 603 vput(vp); 604 LFS_SEGENTRY(sup, fs, segno, bp); 605 KASSERT(sup->su_nbytes >= LFS_DINODE1_SIZE); 606 sup->su_nbytes -= LFS_DINODE1_SIZE; 607 LFS_WRITESEGENTRY(sup, fs, segno, bp); 608 609 /* Set up to fall through to next section */ 610 lfs_if_setdaddr(fs, ifp, LFS_UNUSED_DADDR); 611 LFS_BWRITE_LOG(bp); 612 LFS_IENTRY(ifp, fs, ino, bp); 613 } 614 #endif 615 616 if (lfs_if_getdaddr(fs, ifp) == LFS_UNUSED_DADDR) { 617 if (firstino == LFS_UNUSED_INUM) 618 firstino = ino; 619 else { 620 brelse(bp, 0); 621 622 LFS_IENTRY(ifp, fs, lastino, bp); 623 lfs_if_setnextfree(fs, ifp, ino); 624 LFS_BWRITE_LOG(bp); 625 626 LFS_IENTRY(ifp, fs, ino, bp); 627 } 628 lastino = ino; 629 630 SET_BITMAP_FREE(fs, ino); 631 } 632 633 if ((ino + 1) % lfs_sb_getifpb(fs) == 0) 634 brelse(bp, 0); 635 } 636 637 LFS_PUT_HEADFREE(fs, cip, bp, firstino); 638 LFS_PUT_TAILFREE(fs, cip, bp, lastino); 639 640 lfs_segunlock(fs); 641 } 642 643 void 644 lfs_orphan(struct lfs *fs, ino_t ino) 645 { 646 IFILE *ifp; 647 struct buf *bp; 648 649 LFS_IENTRY(ifp, fs, ino, bp); 650 lfs_if_setnextfree(fs, ifp, LFS_ORPHAN_NEXTFREE); 651 LFS_BWRITE_LOG(bp); 652 } 653