Deleted Added
full compact
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 ---