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