suj.c (218604) | suj.c (221110) |
---|---|
1/*- 2 * Copyright 2009, 2010 Jeffrey W. Roberson <jeff@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> | 1/*- 2 * Copyright 2009, 2010 Jeffrey W. Roberson <jeff@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> |
28__FBSDID("$FreeBSD: head/sbin/fsck_ffs/suj.c 218604 2011-02-12 13:17:14Z kib $"); | 28__FBSDID("$FreeBSD: head/sbin/fsck_ffs/suj.c 221110 2011-04-27 02:55:03Z des $"); |
29 30#include <sys/param.h> 31#include <sys/disk.h> 32#include <sys/disklabel.h> 33#include <sys/mount.h> 34#include <sys/stat.h> 35 36#include <ufs/ufs/ufsmount.h> --- 480 unchanged lines hidden (view full) --- 517 for (i = brec->jb_oldfrags; i < brec->jb_oldfrags + brec->jb_frags; i++) 518 *mask |= 1 << i; 519} 520 521/* 522 * Determine whether a given block has been reallocated to a new location. 523 * Returns a mask of overlapping bits if any frags have been reused or 524 * zero if the block has not been re-used and the contents can be trusted. | 29 30#include <sys/param.h> 31#include <sys/disk.h> 32#include <sys/disklabel.h> 33#include <sys/mount.h> 34#include <sys/stat.h> 35 36#include <ufs/ufs/ufsmount.h> --- 480 unchanged lines hidden (view full) --- 517 for (i = brec->jb_oldfrags; i < brec->jb_oldfrags + brec->jb_frags; i++) 518 *mask |= 1 << i; 519} 520 521/* 522 * Determine whether a given block has been reallocated to a new location. 523 * Returns a mask of overlapping bits if any frags have been reused or 524 * zero if the block has not been re-used and the contents can be trusted. |
525 * | 525 * |
526 * This is used to ensure that an orphaned pointer due to truncate is safe 527 * to be freed. The mask value can be used to free partial blocks. 528 */ 529static int 530blk_freemask(ufs2_daddr_t blk, ino_t ino, ufs_lbn_t lbn, int frags) 531{ 532 struct suj_blk *sblk; 533 struct suj_rec *srec; --- 15 unchanged lines hidden (view full) --- 549 off = blk - sblk->sb_blk; 550 TAILQ_FOREACH(srec, &sblk->sb_recs, sr_next) { 551 brec = (struct jblkrec *)srec->sr_rec; 552 /* 553 * If the block overlaps but does not match 554 * exactly it's a new allocation. If it matches 555 * exactly this record refers to the current 556 * location. | 526 * This is used to ensure that an orphaned pointer due to truncate is safe 527 * to be freed. The mask value can be used to free partial blocks. 528 */ 529static int 530blk_freemask(ufs2_daddr_t blk, ino_t ino, ufs_lbn_t lbn, int frags) 531{ 532 struct suj_blk *sblk; 533 struct suj_rec *srec; --- 15 unchanged lines hidden (view full) --- 549 off = blk - sblk->sb_blk; 550 TAILQ_FOREACH(srec, &sblk->sb_recs, sr_next) { 551 brec = (struct jblkrec *)srec->sr_rec; 552 /* 553 * If the block overlaps but does not match 554 * exactly it's a new allocation. If it matches 555 * exactly this record refers to the current 556 * location. |
557 */ | 557 */ |
558 if (blk_overlaps(brec, blk, frags) == 0) 559 continue; 560 if (blk_equals(brec, ino, lbn, blk, frags) == 1) 561 mask = 0; 562 else 563 blk_setmask(brec, &mask); 564 } 565 if (debug) --- 5 unchanged lines hidden (view full) --- 571/* 572 * Determine whether it is safe to follow an indirect. It is not safe 573 * if any part of the indirect has been reallocated or the last journal 574 * entry was an allocation. Just allocated indirects may not have valid 575 * pointers yet and all of their children will have their own records. 576 * It is also not safe to follow an indirect if the cg bitmap has been 577 * cleared as a new allocation may write to the block prior to the journal 578 * being written. | 558 if (blk_overlaps(brec, blk, frags) == 0) 559 continue; 560 if (blk_equals(brec, ino, lbn, blk, frags) == 1) 561 mask = 0; 562 else 563 blk_setmask(brec, &mask); 564 } 565 if (debug) --- 5 unchanged lines hidden (view full) --- 571/* 572 * Determine whether it is safe to follow an indirect. It is not safe 573 * if any part of the indirect has been reallocated or the last journal 574 * entry was an allocation. Just allocated indirects may not have valid 575 * pointers yet and all of their children will have their own records. 576 * It is also not safe to follow an indirect if the cg bitmap has been 577 * cleared as a new allocation may write to the block prior to the journal 578 * being written. |
579 * | 579 * |
580 * Returns 1 if it's safe to follow the indirect and 0 otherwise. 581 */ 582static int 583blk_isindir(ufs2_daddr_t blk, ino_t ino, ufs_lbn_t lbn) 584{ 585 struct suj_blk *sblk; 586 struct jblkrec *brec; 587 --- 125 unchanged lines hidden (view full) --- 713 if (level == 0 && lbn < 0) 714 err_suj("Invalid lbn %jd\n", lbn); 715 bap2 = (void *)dblk_read(blk, fs->fs_bsize); 716 bap1 = (void *)bap2; 717 lbnadd = 1; 718 base = -(cur + level); 719 for (i = level; i > 0; i--) 720 lbnadd *= NINDIR(fs); | 580 * Returns 1 if it's safe to follow the indirect and 0 otherwise. 581 */ 582static int 583blk_isindir(ufs2_daddr_t blk, ino_t ino, ufs_lbn_t lbn) 584{ 585 struct suj_blk *sblk; 586 struct jblkrec *brec; 587 --- 125 unchanged lines hidden (view full) --- 713 if (level == 0 && lbn < 0) 714 err_suj("Invalid lbn %jd\n", lbn); 715 bap2 = (void *)dblk_read(blk, fs->fs_bsize); 716 bap1 = (void *)bap2; 717 lbnadd = 1; 718 base = -(cur + level); 719 for (i = level; i > 0; i--) 720 lbnadd *= NINDIR(fs); |
721 if (lbn > 0) | 721 if (lbn > 0) |
722 i = (lbn - base) / lbnadd; 723 else 724 i = (-lbn - base) / lbnadd; 725 if (i < 0 || i >= NINDIR(fs)) 726 err_suj("Invalid indirect index %d produced by lbn %jd\n", 727 i, lbn); 728 if (level == 0) 729 cur = base + (i * lbnadd); --- 837 unchanged lines hidden (view full) --- 1567 } 1568 ino_dirty(ino); 1569 /* 1570 * Now that we've freed any whole blocks that exceed the desired 1571 * truncation size, figure out how many blocks remain and what the 1572 * last populated lbn is. We will set the size to this last lbn 1573 * rather than worrying about allocating the final lbn as the kernel 1574 * would've done. This is consistent with normal fsck behavior. | 722 i = (lbn - base) / lbnadd; 723 else 724 i = (-lbn - base) / lbnadd; 725 if (i < 0 || i >= NINDIR(fs)) 726 err_suj("Invalid indirect index %d produced by lbn %jd\n", 727 i, lbn); 728 if (level == 0) 729 cur = base + (i * lbnadd); --- 837 unchanged lines hidden (view full) --- 1567 } 1568 ino_dirty(ino); 1569 /* 1570 * Now that we've freed any whole blocks that exceed the desired 1571 * truncation size, figure out how many blocks remain and what the 1572 * last populated lbn is. We will set the size to this last lbn 1573 * rather than worrying about allocating the final lbn as the kernel 1574 * would've done. This is consistent with normal fsck behavior. |
1575 */ | 1575 */ |
1576 visitlbn = 0; 1577 totalfrags = ino_visit(ip, ino, null_visit, VISIT_INDIR | VISIT_EXT); 1578 if (size > lblktosize(fs, visitlbn + 1)) 1579 size = lblktosize(fs, visitlbn + 1); 1580 /* 1581 * If we're truncating direct blocks we have to adjust frags 1582 * accordingly. 1583 */ --- 61 unchanged lines hidden (view full) --- 1645 ino = sino->si_ino; 1646 rrec = (struct jrefrec *)TAILQ_FIRST(&sino->si_recs)->sr_rec; 1647 nlink = rrec->jr_nlink; 1648 newlinks = 0; 1649 dotlinks = 0; 1650 removes = sino->si_nlinkadj; 1651 TAILQ_FOREACH(srec, &sino->si_recs, sr_next) { 1652 rrec = (struct jrefrec *)srec->sr_rec; | 1576 visitlbn = 0; 1577 totalfrags = ino_visit(ip, ino, null_visit, VISIT_INDIR | VISIT_EXT); 1578 if (size > lblktosize(fs, visitlbn + 1)) 1579 size = lblktosize(fs, visitlbn + 1); 1580 /* 1581 * If we're truncating direct blocks we have to adjust frags 1582 * accordingly. 1583 */ --- 61 unchanged lines hidden (view full) --- 1645 ino = sino->si_ino; 1646 rrec = (struct jrefrec *)TAILQ_FIRST(&sino->si_recs)->sr_rec; 1647 nlink = rrec->jr_nlink; 1648 newlinks = 0; 1649 dotlinks = 0; 1650 removes = sino->si_nlinkadj; 1651 TAILQ_FOREACH(srec, &sino->si_recs, sr_next) { 1652 rrec = (struct jrefrec *)srec->sr_rec; |
1653 isat = ino_isat(rrec->jr_parent, rrec->jr_diroff, | 1653 isat = ino_isat(rrec->jr_parent, rrec->jr_diroff, |
1654 rrec->jr_ino, &mode, &isdot); 1655 if (isat && (mode & IFMT) != (rrec->jr_mode & IFMT)) 1656 err_suj("Inode mode/directory type mismatch %o != %o\n", 1657 mode, rrec->jr_mode); 1658 if (debug) 1659 printf("jrefrec: op %d ino %d, nlink %d, parent %d, " 1660 "diroff %jd, mode %o, isat %d, isdot %d\n", 1661 rrec->jr_op, rrec->jr_ino, rrec->jr_nlink, --- 285 unchanged lines hidden (view full) --- 1947 struct jrefrec *refrec; 1948 struct jmvrec *mvrec; 1949 struct suj_ino *sino; 1950 struct suj_rec *srec; 1951 1952 mvrec = &rec->rec_jmvrec; 1953 refrec = &rec->rec_jrefrec; 1954 if (debug && mvrec->jm_op == JOP_MVREF) | 1654 rrec->jr_ino, &mode, &isdot); 1655 if (isat && (mode & IFMT) != (rrec->jr_mode & IFMT)) 1656 err_suj("Inode mode/directory type mismatch %o != %o\n", 1657 mode, rrec->jr_mode); 1658 if (debug) 1659 printf("jrefrec: op %d ino %d, nlink %d, parent %d, " 1660 "diroff %jd, mode %o, isat %d, isdot %d\n", 1661 rrec->jr_op, rrec->jr_ino, rrec->jr_nlink, --- 285 unchanged lines hidden (view full) --- 1947 struct jrefrec *refrec; 1948 struct jmvrec *mvrec; 1949 struct suj_ino *sino; 1950 struct suj_rec *srec; 1951 1952 mvrec = &rec->rec_jmvrec; 1953 refrec = &rec->rec_jrefrec; 1954 if (debug && mvrec->jm_op == JOP_MVREF) |
1955 printf("ino move: ino %d, parent %d, diroff %jd, oldoff %jd\n", | 1955 printf("ino move: ino %d, parent %d, diroff %jd, oldoff %jd\n", |
1956 mvrec->jm_ino, mvrec->jm_parent, mvrec->jm_newoff, 1957 mvrec->jm_oldoff); 1958 else if (debug && 1959 (refrec->jr_op == JOP_ADDREF || refrec->jr_op == JOP_REMREF)) 1960 printf("ino ref: op %d, ino %d, nlink %d, " | 1956 mvrec->jm_ino, mvrec->jm_parent, mvrec->jm_newoff, 1957 mvrec->jm_oldoff); 1958 else if (debug && 1959 (refrec->jr_op == JOP_ADDREF || refrec->jr_op == JOP_REMREF)) 1960 printf("ino ref: op %d, ino %d, nlink %d, " |
1961 "parent %d, diroff %jd\n", | 1961 "parent %d, diroff %jd\n", |
1962 refrec->jr_op, refrec->jr_ino, refrec->jr_nlink, 1963 refrec->jr_parent, refrec->jr_diroff); 1964 /* 1965 * Lookup the ino and clear truncate if one is found. Partial 1966 * truncates are always done synchronously so if we discover 1967 * an operation that requires a lock the truncation has completed 1968 * and can be discarded. 1969 */ --- 355 unchanged lines hidden (view full) --- 2325 newseq = seg->ss_rec.jsr_seq; 2326 for (;;) { 2327 seg = TAILQ_LAST(&allsegs, seghd); 2328 if (seg->ss_rec.jsr_seq >= newseq) 2329 break; 2330 TAILQ_REMOVE(&allsegs, seg, ss_next); 2331 TAILQ_INSERT_HEAD(&allsegs, seg, ss_next); 2332 newseq = seg->ss_rec.jsr_seq; | 1962 refrec->jr_op, refrec->jr_ino, refrec->jr_nlink, 1963 refrec->jr_parent, refrec->jr_diroff); 1964 /* 1965 * Lookup the ino and clear truncate if one is found. Partial 1966 * truncates are always done synchronously so if we discover 1967 * an operation that requires a lock the truncation has completed 1968 * and can be discarded. 1969 */ --- 355 unchanged lines hidden (view full) --- 2325 newseq = seg->ss_rec.jsr_seq; 2326 for (;;) { 2327 seg = TAILQ_LAST(&allsegs, seghd); 2328 if (seg->ss_rec.jsr_seq >= newseq) 2329 break; 2330 TAILQ_REMOVE(&allsegs, seg, ss_next); 2331 TAILQ_INSERT_HEAD(&allsegs, seg, ss_next); 2332 newseq = seg->ss_rec.jsr_seq; |
2333 | 2333 |
2334 } 2335 if (newseq != oldseq) { 2336 err_suj("Journal file sequence mismatch %jd != %jd\n", 2337 newseq, oldseq); 2338 } 2339 /* 2340 * The kernel may asynchronously write segments which can create 2341 * gaps in the sequence space. Throw away any segments after the --- 262 unchanged lines hidden (view full) --- 2604 } 2605 /* 2606 * Verify that all blocks in the segment are present. 2607 */ 2608 for (i = 1; i < blocks; i++) { 2609 recn = (void *)((uintptr_t)rec) + i * 2610 real_dev_bsize; 2611 if (recn->jsr_seq == rec->jsr_seq && | 2334 } 2335 if (newseq != oldseq) { 2336 err_suj("Journal file sequence mismatch %jd != %jd\n", 2337 newseq, oldseq); 2338 } 2339 /* 2340 * The kernel may asynchronously write segments which can create 2341 * gaps in the sequence space. Throw away any segments after the --- 262 unchanged lines hidden (view full) --- 2604 } 2605 /* 2606 * Verify that all blocks in the segment are present. 2607 */ 2608 for (i = 1; i < blocks; i++) { 2609 recn = (void *)((uintptr_t)rec) + i * 2610 real_dev_bsize; 2611 if (recn->jsr_seq == rec->jsr_seq && |
2612 recn->jsr_time == rec->jsr_time) | 2612 recn->jsr_time == rec->jsr_time) |
2613 continue; 2614 if (debug) 2615 printf("Incomplete record %jd (%d)\n", 2616 rec->jsr_seq, i); 2617 recsize = i * real_dev_bsize; 2618 jblocks_advance(suj_jblocks, recsize); 2619 goto restart; 2620 } --- 145 unchanged lines hidden --- | 2613 continue; 2614 if (debug) 2615 printf("Incomplete record %jd (%d)\n", 2616 rec->jsr_seq, i); 2617 recsize = i * real_dev_bsize; 2618 jblocks_advance(suj_jblocks, recsize); 2619 goto restart; 2620 } --- 145 unchanged lines hidden --- |