1 /* $NetBSD: pass6.c,v 1.32 2013/10/19 01:09:58 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2003 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 #include <sys/types.h> 33 #include <sys/param.h> 34 #include <sys/time.h> 35 #include <sys/buf.h> 36 #include <sys/mount.h> 37 38 #define VU_DIROP 0x01000000 /* XXX XXX from sys/vnode.h */ 39 #define vnode uvnode 40 #include <ufs/lfs/lfs.h> 41 #include <ufs/lfs/lfs_inode.h> 42 #undef vnode 43 44 #include <assert.h> 45 #include <err.h> 46 #include <signal.h> 47 #include <string.h> 48 #include <stdio.h> 49 #include <stdlib.h> 50 #include <util.h> 51 52 #include "bufcache.h" 53 #include "vnode.h" 54 #include "lfs_user.h" 55 #include "segwrite.h" 56 57 #include "fsck.h" 58 #include "extern.h" 59 #include "fsutil.h" 60 61 extern u_int32_t cksum(void *, size_t); 62 extern u_int32_t lfs_sb_cksum(struct dlfs *); 63 64 extern ulfs_daddr_t badblk; 65 extern SEGUSE *seg_table; 66 67 static int nnewblocks; 68 69 /* 70 * Our own copy of lfs_update_single so we can account in seg_table 71 * as well as the Ifile; and so we can add the blocks to their new 72 * segment. 73 * 74 * Change the given block's address to ndaddr, finding its previous 75 * location using ulfs_bmaparray(). 76 * 77 * Account for this change in the segment table. 78 */ 79 static void 80 rfw_update_single(struct uvnode *vp, daddr_t lbn, ulfs_daddr_t ndaddr, int size) 81 { 82 SEGUSE *sup; 83 struct ubuf *bp; 84 struct indir a[ULFS_NIADDR + 2], *ap; 85 struct inode *ip; 86 daddr_t daddr, ooff; 87 int num, error; 88 int i, osize = 0; 89 int frags, ofrags = 0; 90 u_int32_t oldsn, sn; 91 92 ip = VTOI(vp); 93 ip->i_flag |= IN_MODIFIED; 94 95 error = ulfs_bmaparray(fs, vp, lbn, &daddr, a, &num); 96 if (error) 97 errx(1, "lfs_updatemeta: ulfs_bmaparray returned %d" 98 " looking up lbn %" PRId64 "\n", error, lbn); 99 if (daddr > 0) 100 daddr = LFS_DBTOFSB(fs, daddr); 101 102 frags = lfs_numfrags(fs, size); 103 switch (num) { 104 case 0: 105 ooff = ip->i_ffs1_db[lbn]; 106 if (ooff <= 0) 107 ip->i_ffs1_blocks += frags; 108 else { 109 /* possible fragment truncation or extension */ 110 ofrags = lfs_numfrags(fs, ip->i_lfs_fragsize[lbn]); 111 ip->i_ffs1_blocks += (frags - ofrags); 112 } 113 ip->i_ffs1_db[lbn] = ndaddr; 114 break; 115 case 1: 116 ooff = ip->i_ffs1_ib[a[0].in_off]; 117 if (ooff <= 0) 118 ip->i_ffs1_blocks += frags; 119 ip->i_ffs1_ib[a[0].in_off] = ndaddr; 120 break; 121 default: 122 ap = &a[num - 1]; 123 if (bread(vp, ap->in_lbn, fs->lfs_bsize, NULL, 0, &bp)) 124 errx(1, "lfs_updatemeta: bread bno %" PRId64, 125 ap->in_lbn); 126 127 ooff = ((ulfs_daddr_t *) bp->b_data)[ap->in_off]; 128 if (ooff <= 0) 129 ip->i_ffs1_blocks += frags; 130 ((ulfs_daddr_t *) bp->b_data)[ap->in_off] = ndaddr; 131 (void) VOP_BWRITE(bp); 132 } 133 134 /* 135 * Update segment usage information, based on old size 136 * and location. 137 */ 138 if (daddr > 0) { 139 oldsn = lfs_dtosn(fs, daddr); 140 if (lbn >= 0 && lbn < ULFS_NDADDR) 141 osize = ip->i_lfs_fragsize[lbn]; 142 else 143 osize = fs->lfs_bsize; 144 LFS_SEGENTRY(sup, fs, oldsn, bp); 145 seg_table[oldsn].su_nbytes -= osize; 146 sup->su_nbytes -= osize; 147 if (!(bp->b_flags & B_GATHERED)) 148 fs->lfs_flags |= LFS_IFDIRTY; 149 LFS_WRITESEGENTRY(sup, fs, oldsn, bp); 150 for (i = 0; i < lfs_btofsb(fs, osize); i++) 151 clrbmap(daddr + i); 152 } 153 154 /* If block is beyond EOF, update size */ 155 if (lbn >= 0 && ip->i_ffs1_size <= (lbn << fs->lfs_bshift)) { 156 ip->i_ffs1_size = (lbn << fs->lfs_bshift) + 1; 157 } 158 159 /* If block frag size is too large for old EOF, update size */ 160 if (lbn < ULFS_NDADDR) { 161 off_t minsize; 162 163 minsize = (lbn << fs->lfs_bshift); 164 minsize += (size - fs->lfs_fsize) + 1; 165 if (ip->i_ffs1_size < minsize) 166 ip->i_ffs1_size = minsize; 167 } 168 169 /* Count for the user */ 170 ++nnewblocks; 171 172 /* Add block to its new segment */ 173 sn = lfs_dtosn(fs, ndaddr); 174 LFS_SEGENTRY(sup, fs, sn, bp); 175 seg_table[sn].su_nbytes += size; 176 sup->su_nbytes += size; 177 if (!(bp->b_flags & B_GATHERED)) 178 fs->lfs_flags |= LFS_IFDIRTY; 179 LFS_WRITESEGENTRY(sup, fs, sn, bp); 180 for (i = 0; i < lfs_btofsb(fs, size); i++) 181 #ifndef VERBOSE_BLOCKMAP 182 setbmap(daddr + i); 183 #else 184 setbmap(daddr + i, ip->i_number); 185 #endif 186 187 /* Check bfree accounting as well */ 188 if (daddr <= 0) { 189 fs->lfs_bfree -= lfs_btofsb(fs, size); 190 } else if (size != osize) { 191 fs->lfs_bfree -= (frags - ofrags); 192 } 193 194 /* 195 * Now that this block has a new address, and its old 196 * segment no longer owns it, we can forget about its 197 * old size. 198 */ 199 if (lbn >= 0 && lbn < ULFS_NDADDR) 200 ip->i_lfs_fragsize[lbn] = size; 201 } 202 203 /* 204 * Remove the vnode from the cache, including any blocks it 205 * may hold. Account the blocks. Finally account the removal 206 * of the inode from its segment. 207 */ 208 static void 209 remove_ino(struct uvnode *vp, ino_t ino) 210 { 211 IFILE *ifp; 212 SEGUSE *sup; 213 CLEANERINFO *cip; 214 struct ubuf *bp, *sbp, *cbp; 215 struct inodesc idesc; 216 ulfs_daddr_t daddr; 217 218 if (debug) 219 pwarn("remove ino %d\n", (int)ino); 220 221 LFS_IENTRY(ifp, fs, ino, bp); 222 daddr = ifp->if_daddr; 223 if (daddr > 0) { 224 ifp->if_daddr = 0x0; 225 226 LFS_GET_HEADFREE(fs, cip, cbp, &(ifp->if_nextfree)); 227 VOP_BWRITE(bp); 228 LFS_PUT_HEADFREE(fs, cip, cbp, ino); 229 sbdirty(); 230 231 if (vp == NULL) 232 vp = lfs_raw_vget(fs, ino, fs->lfs_ivnode->v_fd, daddr); 233 234 LFS_SEGENTRY(sup, fs, lfs_dtosn(fs, daddr), sbp); 235 sup->su_nbytes -= LFS_DINODE1_SIZE; 236 VOP_BWRITE(sbp); 237 seg_table[lfs_dtosn(fs, daddr)].su_nbytes -= LFS_DINODE1_SIZE; 238 } else 239 brelse(bp, 0); 240 241 /* Do on-disk accounting */ 242 if (vp) { 243 idesc.id_number = ino; 244 idesc.id_func = pass4check; /* Delete dinode and blocks */ 245 idesc.id_type = ADDR; 246 idesc.id_lblkno = 0; 247 clri(&idesc, "unknown", 2); /* XXX magic number 2 */ 248 /* vp has been destroyed */ 249 } 250 } 251 252 /* 253 * Use FIP records to update blocks, if the generation number matches. 254 */ 255 static void 256 pass6harvest(ulfs_daddr_t daddr, FINFO *fip) 257 { 258 struct uvnode *vp; 259 int i; 260 size_t size; 261 262 vp = vget(fs, fip->fi_ino); 263 if (vp && vp != fs->lfs_ivnode && 264 VTOI(vp)->i_ffs1_gen == fip->fi_version) { 265 for (i = 0; i < fip->fi_nblocks; i++) { 266 size = (i == fip->fi_nblocks - 1 ? 267 fip->fi_lastlength : fs->lfs_bsize); 268 if (debug) 269 pwarn("ino %lld lbn %lld -> 0x%lx\n", 270 (long long)fip->fi_ino, 271 (long long)fip->fi_blocks[i], 272 (long)daddr); 273 rfw_update_single(vp, fip->fi_blocks[i], daddr, size); 274 daddr += lfs_btofsb(fs, size); 275 } 276 } 277 } 278 279 /* 280 * Check validity of blocks on roll-forward inodes. 281 */ 282 int 283 pass6check(struct inodesc * idesc) 284 { 285 int i, sn, anyout, anynew; 286 287 /* Brand new blocks are always OK */ 288 if (idesc->id_blkno == UNWRITTEN) 289 return KEEPON; 290 291 /* Check that the blocks do not lie within clean segments. */ 292 anyout = anynew = 0; 293 for (i = 0; i < idesc->id_numfrags; i++) { 294 sn = lfs_dtosn(fs, idesc->id_blkno + i); 295 if (sn < 0 || sn >= fs->lfs_nseg || 296 (seg_table[sn].su_flags & SEGUSE_DIRTY) == 0) { 297 anyout = 1; 298 break; 299 } 300 if (seg_table[sn].su_flags & SEGUSE_ACTIVE) { 301 if (sn != lfs_dtosn(fs, fs->lfs_offset) || 302 idesc->id_blkno > fs->lfs_offset) { 303 ++anynew; 304 } 305 } 306 if (!anynew) { 307 /* Clear so pass1check won't be surprised */ 308 clrbmap(idesc->id_blkno + i); 309 seg_table[sn].su_nbytes -= lfs_fsbtob(fs, 1); 310 } 311 } 312 if (anyout) { 313 blkerror(idesc->id_number, "BAD", idesc->id_blkno); 314 if (badblk++ >= MAXBAD) { 315 pwarn("EXCESSIVE BAD BLKS I=%llu", 316 (unsigned long long)idesc->id_number); 317 if (preen) 318 pwarn(" (SKIPPING)\n"); 319 else if (reply("CONTINUE") == 0) 320 err(EEXIT, "%s", ""); 321 return (STOP); 322 } 323 } 324 325 return pass1check(idesc); 326 } 327 328 static void 329 account_indir(struct uvnode *vp, struct ulfs1_dinode *dp, daddr_t ilbn, daddr_t daddr, int lvl) 330 { 331 struct ubuf *bp; 332 int32_t *dap, *odap, *buf, *obuf; 333 daddr_t lbn; 334 335 if (lvl == 0) 336 lbn = -ilbn; 337 else 338 lbn = ilbn + 1; 339 bread(fs->lfs_devvp, LFS_FSBTODB(fs, daddr), fs->lfs_bsize, NULL, 0, &bp); 340 buf = emalloc(fs->lfs_bsize); 341 memcpy(buf, bp->b_data, fs->lfs_bsize); 342 brelse(bp, 0); 343 344 obuf = emalloc(fs->lfs_bsize); 345 if (vp) { 346 bread(vp, ilbn, fs->lfs_bsize, NULL, 0, &bp); 347 memcpy(obuf, bp->b_data, fs->lfs_bsize); 348 brelse(bp, 0); 349 } else 350 memset(obuf, 0, fs->lfs_bsize); 351 352 for (dap = buf, odap = obuf; 353 dap < (int32_t *)((char *)buf + fs->lfs_bsize); 354 ++dap, ++odap) { 355 if (*dap > 0 && *dap != *odap) { 356 rfw_update_single(vp, lbn, *dap, lfs_dblksize(fs, dp, lbn)); 357 if (lvl > 0) 358 account_indir(vp, dp, lbn, *dap, lvl - 1); 359 } 360 if (lvl == 0) 361 ++lbn; 362 else if (lvl == 1) 363 lbn -= LFS_NINDIR(fs); 364 else if (lvl == 2) 365 lbn -= LFS_NINDIR(fs) * LFS_NINDIR(fs); 366 } 367 368 free(obuf); 369 free(buf); 370 } 371 372 /* 373 * Account block changes between new found inode and existing inode. 374 */ 375 static void 376 account_block_changes(struct ulfs1_dinode *dp) 377 { 378 int i; 379 daddr_t lbn, off, odaddr; 380 struct uvnode *vp; 381 struct inode *ip; 382 383 vp = vget(fs, dp->di_inumber); 384 ip = (vp ? VTOI(vp) : NULL); 385 386 /* Check direct block holdings between existing and new */ 387 for (i = 0; i < ULFS_NDADDR; i++) { 388 odaddr = (ip ? ip->i_ffs1_db[i] : 0x0); 389 if (dp->di_db[i] > 0 && dp->di_db[i] != odaddr) 390 rfw_update_single(vp, i, dp->di_db[i], 391 lfs_dblksize(fs, dp, i)); 392 } 393 394 /* Check indirect block holdings between existing and new */ 395 off = 0; 396 for (i = 0; i < ULFS_NIADDR; i++) { 397 odaddr = (ip ? ip->i_ffs1_ib[i] : 0x0); 398 if (dp->di_ib[i] > 0 && dp->di_ib[i] != odaddr) { 399 lbn = -(ULFS_NDADDR + off + i); 400 rfw_update_single(vp, i, dp->di_ib[i], fs->lfs_bsize); 401 account_indir(vp, dp, lbn, dp->di_ib[i], i); 402 } 403 if (off == 0) 404 off = LFS_NINDIR(fs); 405 else 406 off *= LFS_NINDIR(fs); 407 } 408 } 409 410 /* 411 * Give a previously allocated inode a new address; do segment 412 * accounting if necessary. 413 * 414 * Caller has ensured that this inode is not on the free list, so no 415 * free list accounting is done. 416 */ 417 static void 418 readdress_inode(struct ulfs1_dinode *dp, ulfs_daddr_t daddr) 419 { 420 IFILE *ifp; 421 SEGUSE *sup; 422 struct ubuf *bp; 423 int sn; 424 ulfs_daddr_t odaddr; 425 ino_t thisino = dp->di_inumber; 426 struct uvnode *vp; 427 428 /* Recursively check all block holdings, account changes */ 429 account_block_changes(dp); 430 431 /* Move ifile pointer to this location */ 432 LFS_IENTRY(ifp, fs, thisino, bp); 433 odaddr = ifp->if_daddr; 434 assert(odaddr != 0); 435 ifp->if_daddr = daddr; 436 VOP_BWRITE(bp); 437 438 if (debug) 439 pwarn("readdress ino %d from 0x%x to 0x%x mode %o nlink %d\n", 440 (int)dp->di_inumber, 441 (unsigned)odaddr, 442 (unsigned)daddr, 443 (int)dp->di_mode, (int)dp->di_nlink); 444 445 /* Copy over preexisting in-core inode, if any */ 446 vp = vget(fs, thisino); 447 memcpy(VTOI(vp)->i_din.ffs1_din, dp, sizeof(*dp)); 448 449 /* Finally account the inode itself */ 450 sn = lfs_dtosn(fs, odaddr); 451 LFS_SEGENTRY(sup, fs, sn, bp); 452 sup->su_nbytes -= LFS_DINODE1_SIZE; 453 VOP_BWRITE(bp); 454 seg_table[sn].su_nbytes -= LFS_DINODE1_SIZE; 455 456 sn = lfs_dtosn(fs, daddr); 457 LFS_SEGENTRY(sup, fs, sn, bp); 458 sup->su_nbytes += LFS_DINODE1_SIZE; 459 VOP_BWRITE(bp); 460 seg_table[sn].su_nbytes += LFS_DINODE1_SIZE; 461 } 462 463 /* 464 * Allocate the given inode from the free list. 465 */ 466 static void 467 alloc_inode(ino_t thisino, ulfs_daddr_t daddr) 468 { 469 ino_t ino, nextfree, oldhead; 470 IFILE *ifp; 471 SEGUSE *sup; 472 struct ubuf *bp, *cbp; 473 CLEANERINFO *cip; 474 475 if (debug) 476 pwarn("allocating ino %d at 0x%x\n", (int)thisino, 477 (unsigned)daddr); 478 while (thisino >= maxino) { 479 extend_ifile(fs); 480 } 481 482 LFS_IENTRY(ifp, fs, thisino, bp); 483 if (ifp->if_daddr != 0) { 484 pwarn("allocated inode %lld already allocated\n", 485 (long long)thisino); 486 } 487 nextfree = ifp->if_nextfree; 488 ifp->if_nextfree = 0; 489 ifp->if_daddr = daddr; 490 VOP_BWRITE(bp); 491 492 LFS_GET_HEADFREE(fs, cip, cbp, &oldhead); 493 if (oldhead == thisino) { 494 LFS_PUT_HEADFREE(fs, cip, cbp, nextfree); 495 sbdirty(); 496 if (nextfree == 0) { 497 extend_ifile(fs); 498 } 499 } else { 500 /* Search the free list for this inode */ 501 ino = oldhead; 502 while (ino) { 503 LFS_IENTRY(ifp, fs, ino, bp); 504 assert(ifp->if_nextfree != ino); 505 if (ifp->if_nextfree == thisino) { 506 ifp->if_nextfree = nextfree; 507 VOP_BWRITE(bp); 508 if (nextfree == 0) 509 LFS_PUT_TAILFREE(fs, cip, cbp, ino); 510 break; 511 } else 512 ino = ifp->if_nextfree; 513 brelse(bp, 0); 514 } 515 } 516 517 /* Account for new location */ 518 LFS_SEGENTRY(sup, fs, lfs_dtosn(fs, daddr), bp); 519 sup->su_nbytes += LFS_DINODE1_SIZE; 520 VOP_BWRITE(bp); 521 seg_table[lfs_dtosn(fs, daddr)].su_nbytes += LFS_DINODE1_SIZE; 522 } 523 524 /* 525 * Roll forward from the last verified checkpoint. 526 * 527 * Basic strategy: 528 * 529 * Run through the summaries finding the last valid partial segment. 530 * Note segment numbers as we go. For each inode that we find, compare 531 * its generation number; if newer than old inode's (or if old inode is 532 * USTATE), change to that inode. Recursively look at inode blocks that 533 * do not have their old disk addresses. These addresses must lie in 534 * segments we have seen already in our roll forward. 535 * 536 * A second pass through the past-checkpoint area verifies the validity 537 * of these new blocks, as well as updating other blocks that do not 538 * have corresponding new inodes (but their generation number must match 539 * the old generation number). 540 */ 541 void 542 pass6(void) 543 { 544 ulfs_daddr_t daddr, ibdaddr, odaddr, lastgood, *idaddrp; 545 struct uvnode *vp, *devvp; 546 CLEANERINFO *cip; 547 SEGUSE *sup; 548 SEGSUM *sp; 549 struct ubuf *bp, *ibp, *sbp, *cbp; 550 struct ulfs1_dinode *dp; 551 struct inodesc idesc; 552 int i, j, bc, hassuper; 553 int nnewfiles, ndelfiles, nmvfiles; 554 int sn, curseg; 555 char *ibbuf; 556 long lastserial; 557 558 devvp = fs->lfs_devvp; 559 560 /* If we can't roll forward because of created files, don't try */ 561 if (no_roll_forward) { 562 if (debug) 563 pwarn("not rolling forward due to possible allocation conflict\n"); 564 return; 565 } 566 567 /* Find last valid partial segment */ 568 lastgood = try_verify(fs, devvp, 0, debug); 569 if (lastgood == fs->lfs_offset) { 570 if (debug) 571 pwarn("not rolling forward, nothing to recover\n"); 572 return; 573 } 574 575 if (debug) 576 pwarn("could roll forward from 0x%" PRIx32 " to 0x%" PRIx32 "\n", 577 fs->lfs_offset, lastgood); 578 579 if (!preen && reply("ROLL FORWARD") == 0) 580 return; 581 /* 582 * Pass 1: find inode blocks. We ignore the Ifile inode but accept 583 * changes to any other inode. 584 */ 585 586 ibbuf = emalloc(fs->lfs_ibsize); 587 nnewfiles = ndelfiles = nmvfiles = nnewblocks = 0; 588 daddr = fs->lfs_offset; 589 hassuper = 0; 590 lastserial = 0; 591 while (daddr != lastgood) { 592 seg_table[lfs_dtosn(fs, daddr)].su_flags |= SEGUSE_DIRTY | SEGUSE_ACTIVE; 593 LFS_SEGENTRY(sup, fs, lfs_dtosn(fs, daddr), sbp); 594 sup->su_flags |= SEGUSE_DIRTY; 595 VOP_BWRITE(sbp); 596 597 /* Could be a superblock */ 598 if (lfs_sntod(fs, lfs_dtosn(fs, daddr)) == daddr) { 599 if (daddr == fs->lfs_start) { 600 ++hassuper; 601 daddr += lfs_btofsb(fs, LFS_LABELPAD); 602 } 603 for (i = 0; i < LFS_MAXNUMSB; i++) { 604 if (daddr == fs->lfs_sboffs[i]) { 605 ++hassuper; 606 daddr += lfs_btofsb(fs, LFS_SBPAD); 607 } 608 if (daddr < fs->lfs_sboffs[i]) 609 break; 610 } 611 } 612 613 /* Read in summary block */ 614 bread(devvp, LFS_FSBTODB(fs, daddr), fs->lfs_sumsize, NULL, 0, &bp); 615 sp = (SEGSUM *)bp->b_data; 616 if (debug) 617 pwarn("sum at 0x%x: ninos=%d nfinfo=%d\n", 618 (unsigned)daddr, (int)sp->ss_ninos, 619 (int)sp->ss_nfinfo); 620 621 /* We have verified that this is a good summary. */ 622 LFS_SEGENTRY(sup, fs, lfs_dtosn(fs, daddr), sbp); 623 ++sup->su_nsums; 624 VOP_BWRITE(sbp); 625 fs->lfs_bfree -= lfs_btofsb(fs, fs->lfs_sumsize); 626 fs->lfs_dmeta += lfs_btofsb(fs, fs->lfs_sumsize); 627 sbdirty(); 628 if (lfs_sntod(fs, lfs_dtosn(fs, daddr)) == daddr + 629 hassuper * lfs_btofsb(fs, LFS_SBPAD) && 630 lfs_dtosn(fs, daddr) != lfs_dtosn(fs, fs->lfs_offset)) { 631 --fs->lfs_nclean; 632 sbdirty(); 633 } 634 635 /* Find inodes, look at generation number. */ 636 if (sp->ss_ninos) { 637 LFS_SEGENTRY(sup, fs, lfs_dtosn(fs, daddr), sbp); 638 sup->su_ninos += howmany(sp->ss_ninos, LFS_INOPB(fs)); 639 VOP_BWRITE(sbp); 640 fs->lfs_dmeta += lfs_btofsb(fs, howmany(sp->ss_ninos, 641 LFS_INOPB(fs)) * 642 fs->lfs_ibsize); 643 } 644 idaddrp = ((ulfs_daddr_t *)((char *)bp->b_data + fs->lfs_sumsize)); 645 for (i = 0; i < howmany(sp->ss_ninos, LFS_INOPB(fs)); i++) { 646 ino_t *inums; 647 648 inums = ecalloc(LFS_INOPB(fs) + 1, sizeof(*inums)); 649 ibdaddr = *--idaddrp; 650 fs->lfs_bfree -= lfs_btofsb(fs, fs->lfs_ibsize); 651 sbdirty(); 652 bread(devvp, LFS_FSBTODB(fs, ibdaddr), fs->lfs_ibsize, 653 NOCRED, 0, &ibp); 654 memcpy(ibbuf, ibp->b_data, fs->lfs_ibsize); 655 brelse(ibp, 0); 656 657 j = 0; 658 for (dp = (struct ulfs1_dinode *)ibbuf; 659 dp < (struct ulfs1_dinode *)ibbuf + LFS_INOPB(fs); 660 ++dp) { 661 if (dp->di_inumber == 0 || 662 dp->di_inumber == fs->lfs_ifile) 663 continue; 664 /* Basic sanity checks */ 665 if (dp->di_nlink < 0 666 #if 0 667 || dp->di_u.inumber < 0 668 || dp->di_size < 0 669 #endif 670 ) { 671 pwarn("BAD INODE AT 0x%" PRIx32 "\n", 672 ibdaddr); 673 brelse(bp, 0); 674 free(inums); 675 goto out; 676 } 677 678 vp = vget(fs, dp->di_inumber); 679 680 /* 681 * Four cases: 682 * (1) Invalid inode (nlink == 0). 683 * If currently allocated, remove. 684 */ 685 if (dp->di_nlink == 0) { 686 remove_ino(vp, dp->di_inumber); 687 ++ndelfiles; 688 continue; 689 } 690 /* 691 * (2) New valid inode, previously free. 692 * Nothing to do except account 693 * the inode itself, done after the 694 * loop. 695 */ 696 if (vp == NULL) { 697 if (!(sp->ss_flags & SS_DIROP)) 698 pfatal("NEW FILE IN NON-DIROP PARTIAL SEGMENT"); 699 else { 700 inums[j++] = dp->di_inumber; 701 nnewfiles++; 702 } 703 continue; 704 } 705 /* 706 * (3) Valid new version of previously 707 * allocated inode. Delete old file 708 * and proceed as in (2). 709 */ 710 if (vp && VTOI(vp)->i_ffs1_gen < dp->di_gen) { 711 remove_ino(vp, dp->di_inumber); 712 if (!(sp->ss_flags & SS_DIROP)) 713 pfatal("NEW FILE VERSION IN NON-DIROP PARTIAL SEGMENT"); 714 else { 715 inums[j++] = dp->di_inumber; 716 ndelfiles++; 717 nnewfiles++; 718 } 719 continue; 720 } 721 /* 722 * (4) Same version of previously 723 * allocated inode. Move inode to 724 * this location, account inode change 725 * only. We'll pick up any new 726 * blocks when we do the block pass. 727 */ 728 if (vp && VTOI(vp)->i_ffs1_gen == dp->di_gen) { 729 nmvfiles++; 730 readdress_inode(dp, ibdaddr); 731 732 /* Update with new info */ 733 VTOD(vp)->di_mode = dp->di_mode; 734 VTOD(vp)->di_nlink = dp->di_nlink; 735 /* XXX size is important */ 736 VTOD(vp)->di_size = dp->di_size; 737 VTOD(vp)->di_atime = dp->di_atime; 738 VTOD(vp)->di_atimensec = dp->di_atimensec; 739 VTOD(vp)->di_mtime = dp->di_mtime; 740 VTOD(vp)->di_mtimensec = dp->di_mtimensec; 741 VTOD(vp)->di_ctime = dp->di_ctime; 742 VTOD(vp)->di_ctimensec = dp->di_ctimensec; 743 VTOD(vp)->di_flags = dp->di_flags; 744 VTOD(vp)->di_uid = dp->di_uid; 745 VTOD(vp)->di_gid = dp->di_gid; 746 inodirty(VTOI(vp)); 747 } 748 } 749 for (j = 0; inums[j]; j++) { 750 alloc_inode(inums[j], ibdaddr); 751 vp = lfs_raw_vget(fs, inums[j], 752 devvp->v_fd, ibdaddr); 753 /* We'll get the blocks later */ 754 if (debug) 755 pwarn("alloc ino %d nlink %d\n", 756 (int)inums[j], VTOD(vp)->di_nlink); 757 memset(VTOD(vp)->di_db, 0, (ULFS_NDADDR + ULFS_NIADDR) * 758 sizeof(ulfs_daddr_t)); 759 VTOD(vp)->di_blocks = 0; 760 761 vp->v_uflag |= VU_DIROP; 762 inodirty(VTOI(vp)); 763 } 764 free(inums); 765 } 766 767 bc = check_summary(fs, sp, daddr, debug, devvp, NULL); 768 if (bc == 0) { 769 pwarn("unexpected bad seg ptr at 0x%x with serial=%d\n", 770 (int)daddr, (int)sp->ss_serial); 771 brelse(bp, 0); 772 break; 773 } else { 774 if (debug) 775 pwarn("good seg ptr at 0x%x with serial=%d\n", 776 (int)daddr, (int)sp->ss_serial); 777 lastserial = sp->ss_serial; 778 } 779 odaddr = daddr; 780 daddr += lfs_btofsb(fs, fs->lfs_sumsize + bc); 781 if (lfs_dtosn(fs, odaddr) != lfs_dtosn(fs, daddr) || 782 lfs_dtosn(fs, daddr) != lfs_dtosn(fs, daddr + 783 lfs_btofsb(fs, fs->lfs_sumsize + fs->lfs_bsize) - 1)) { 784 daddr = ((SEGSUM *)bp->b_data)->ss_next; 785 } 786 brelse(bp, 0); 787 } 788 789 out: 790 free(ibbuf); 791 792 /* Set serial here, just to be sure (XXX should be right already) */ 793 fs->lfs_serial = lastserial + 1; 794 795 /* 796 * Check our new vnodes. Any blocks must lie in segments that 797 * we've seen before (SEGUSE_DIRTY or SEGUSE_RFW); and the rest 798 * of the pass 1 checks as well. 799 */ 800 memset(&idesc, 0, sizeof(struct inodesc)); 801 idesc.id_type = ADDR; 802 idesc.id_func = pass6check; 803 idesc.id_lblkno = 0; 804 LIST_FOREACH(vp, &vnodelist, v_mntvnodes) { 805 if ((vp->v_uflag & VU_DIROP) == 0) 806 --n_files; /* Don't double count */ 807 checkinode(VTOI(vp)->i_number, &idesc); 808 } 809 810 /* 811 * Second pass. Run through FINFO entries looking for blocks 812 * with the same generation number as files we've seen before. 813 * If they have it, pretend like we just wrote them. We don't 814 * do the pretend-write, though, if we've already seen them 815 * (the accounting would have been done for us already). 816 */ 817 daddr = fs->lfs_offset; 818 while (daddr != lastgood) { 819 if (!(seg_table[lfs_dtosn(fs, daddr)].su_flags & SEGUSE_DIRTY)) { 820 seg_table[lfs_dtosn(fs, daddr)].su_flags |= SEGUSE_DIRTY; 821 LFS_SEGENTRY(sup, fs, lfs_dtosn(fs, daddr), sbp); 822 sup->su_flags |= SEGUSE_DIRTY; 823 VOP_BWRITE(sbp); 824 } 825 826 /* Could be a superblock */ 827 if (lfs_sntod(fs, lfs_dtosn(fs, daddr)) == daddr) { 828 if (daddr == fs->lfs_start) 829 daddr += lfs_btofsb(fs, LFS_LABELPAD); 830 for (i = 0; i < LFS_MAXNUMSB; i++) { 831 if (daddr == fs->lfs_sboffs[i]) { 832 daddr += lfs_btofsb(fs, LFS_SBPAD); 833 } 834 if (daddr < fs->lfs_sboffs[i]) 835 break; 836 } 837 } 838 839 /* Read in summary block */ 840 bread(devvp, LFS_FSBTODB(fs, daddr), fs->lfs_sumsize, NULL, 0, &bp); 841 sp = (SEGSUM *)bp->b_data; 842 bc = check_summary(fs, sp, daddr, debug, devvp, pass6harvest); 843 if (bc == 0) { 844 pwarn("unexpected bad seg ptr [2] at 0x%x with serial=%d\n", 845 (int)daddr, (int)sp->ss_serial); 846 brelse(bp, 0); 847 break; 848 } 849 odaddr = daddr; 850 daddr += lfs_btofsb(fs, fs->lfs_sumsize + bc); 851 fs->lfs_avail -= lfs_btofsb(fs, fs->lfs_sumsize + bc); 852 if (lfs_dtosn(fs, odaddr) != lfs_dtosn(fs, daddr) || 853 lfs_dtosn(fs, daddr) != lfs_dtosn(fs, daddr + 854 lfs_btofsb(fs, fs->lfs_sumsize + fs->lfs_bsize) - 1)) { 855 fs->lfs_avail -= lfs_sntod(fs, lfs_dtosn(fs, daddr) + 1) - daddr; 856 daddr = ((SEGSUM *)bp->b_data)->ss_next; 857 } 858 LFS_CLEANERINFO(cip, fs, cbp); 859 LFS_SYNC_CLEANERINFO(cip, fs, cbp, 0); 860 bp->b_flags |= B_AGE; 861 brelse(bp, 0); 862 } 863 864 /* Final address could also be a superblock */ 865 if (lfs_sntod(fs, lfs_dtosn(fs, lastgood)) == lastgood) { 866 if (lastgood == fs->lfs_start) 867 lastgood += lfs_btofsb(fs, LFS_LABELPAD); 868 for (i = 0; i < LFS_MAXNUMSB; i++) { 869 if (lastgood == fs->lfs_sboffs[i]) 870 lastgood += lfs_btofsb(fs, LFS_SBPAD); 871 if (lastgood < fs->lfs_sboffs[i]) 872 break; 873 } 874 } 875 876 /* Update offset to point at correct location */ 877 fs->lfs_offset = lastgood; 878 fs->lfs_curseg = lfs_sntod(fs, lfs_dtosn(fs, lastgood)); 879 for (sn = curseg = lfs_dtosn(fs, fs->lfs_curseg);;) { 880 sn = (sn + 1) % fs->lfs_nseg; 881 if (sn == curseg) 882 errx(1, "no clean segments"); 883 LFS_SEGENTRY(sup, fs, sn, bp); 884 if ((sup->su_flags & SEGUSE_DIRTY) == 0) { 885 sup->su_flags |= SEGUSE_DIRTY | SEGUSE_ACTIVE; 886 VOP_BWRITE(bp); 887 break; 888 } 889 brelse(bp, 0); 890 } 891 fs->lfs_nextseg = lfs_sntod(fs, sn); 892 893 if (preen) { 894 if (ndelfiles) 895 pwarn("roll forward deleted %d file%s\n", ndelfiles, 896 (ndelfiles > 1 ? "s" : "")); 897 if (nnewfiles) 898 pwarn("roll forward added %d file%s\n", nnewfiles, 899 (nnewfiles > 1 ? "s" : "")); 900 if (nmvfiles) 901 pwarn("roll forward relocated %d inode%s\n", nmvfiles, 902 (nmvfiles > 1 ? "s" : "")); 903 if (nnewblocks) 904 pwarn("roll forward verified %d data block%s\n", nnewblocks, 905 (nnewblocks > 1 ? "s" : "")); 906 if (ndelfiles == 0 && nnewfiles == 0 && nmvfiles == 0 && 907 nnewblocks == 0) 908 pwarn("roll forward produced nothing new\n"); 909 } 910 911 if (!preen) { 912 /* Run pass 5 again (it's quick anyway). */ 913 pwarn("** Phase 6b - Recheck Segment Block Accounting\n"); 914 pass5(); 915 } 916 917 /* Likewise for pass 0 */ 918 if (!preen) 919 pwarn("** Phase 6c - Recheck Inode Free List\n"); 920 pass0(); 921 } 922