gfs2-utils: RHEL7 - gfs2-utils/tests: Fix unit tests for older check libraries
by Andrew Price
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=d496c725...
Commit: d496c725c7566620a587b8d10afe607f0e7e7454
Parent: 4e30050ed287bf96305dbab1f994b0e06096eb4c
Author: Andrew Price <anprice(a)redhat.com>
AuthorDate: Fri Feb 20 10:56:07 2015 +0000
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Wed Apr 1 16:51:35 2015 +0100
gfs2-utils/tests: Fix unit tests for older check libraries
ck_assert_ptr_ne() and ck_assert_uint_eq() appeared some time after
RHEL7 was released and the only value they add is some prettier output
when they fail. Replace calls to these functions with fail_unless() to
ensure check_rgrp.c builds on a wider range of environments.
Signed-off-by: Andrew Price <anprice(a)redhat.com>
---
tests/check_rgrp.c | 14 +++++++-------
1 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/tests/check_rgrp.c b/tests/check_rgrp.c
index e5fca8d..792b3ae 100644
--- a/tests/check_rgrp.c
+++ b/tests/check_rgrp.c
@@ -16,7 +16,7 @@ static lgfs2_rgrps_t mockup_rgrp(void)
uint32_t rgsize = (1024 << 20) / 4096;
sdp = calloc(1, sizeof(*sdp));
- ck_assert_ptr_ne(sdp, NULL);
+ fail_unless(sdp != NULL);
sdp->device.length = rgsize + 20;
sdp->device_fd = -1;
@@ -24,7 +24,7 @@ static lgfs2_rgrps_t mockup_rgrp(void)
compute_constants(sdp);
rgs = lgfs2_rgrps_init(sdp, 0, 0);
- ck_assert_ptr_ne(rgs, NULL);
+ fail_unless(rgs != NULL);
lgfs2_rgrps_plan(rgs, sdp->device.length - 16, rgsize);
@@ -32,11 +32,11 @@ static lgfs2_rgrps_t mockup_rgrp(void)
ck_assert(addr != 0);
rg = lgfs2_rgrps_append(rgs, &ri);
- ck_assert_ptr_ne(rg, NULL);
+ fail_unless(rg != NULL);
for (i = 0; i < rg->ri.ri_length; i++) {
rg->bits[i].bi_bh = bget(sdp, rg->ri.ri_addr + i);
- ck_assert_ptr_ne(rg->bits[i].bi_bh, NULL);
+ fail_unless(rg->bits[i].bi_bh != NULL);
}
return rgs;
}
@@ -44,7 +44,7 @@ static lgfs2_rgrps_t mockup_rgrp(void)
START_TEST(test_mockup_rgrp)
{
lgfs2_rgrps_t rgs = mockup_rgrp();
- ck_assert_ptr_ne(rgs, NULL);
+ fail_unless(rgs != NULL);
}
END_TEST
@@ -66,7 +66,7 @@ START_TEST(test_rbm_find_good)
ck_assert_int_eq(err, 0);
addr = lgfs2_rbm_to_block(&rbm);
- ck_assert_uint_eq(addr, rbm.rgd->ri.ri_data0);
+ fail_unless(addr == rbm.rgd->ri.ri_data0);
}
}
END_TEST
@@ -110,7 +110,7 @@ START_TEST(test_rbm_find_lastblock)
ck_assert_int_eq(err, 0);
addr = lgfs2_rbm_to_block(&rbm);
- ck_assert_uint_eq(addr, rg->ri.ri_data0 + rg->ri.ri_data - 1);
+ fail_unless(addr == (rg->ri.ri_data0 + rg->ri.ri_data - 1));
}
END_TEST
9 years
gfs2-utils: RHEL7 - fsck.gfs2: Fix journal sequence number reporting problem
by Andrew Price
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=4e30050e...
Commit: 4e30050ed287bf96305dbab1f994b0e06096eb4c
Parent: 5c82136b8b26b063542af8850c494cacb5c97c87
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Fri Jan 23 09:12:57 2015 -0600
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Wed Apr 1 16:51:35 2015 +0100
fsck.gfs2: Fix journal sequence number reporting problem
This bug was spotted by coverity. The fsck.gfs2 should include a line
to report the number of journal sequence errors fixed. It was coded
improperly so that it was never displayed. This patch fixes the code
so that the message will be printed properly.
---
gfs2/fsck/fs_recovery.c | 9 +++++----
1 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/gfs2/fsck/fs_recovery.c b/gfs2/fsck/fs_recovery.c
index abb8187..9be5a95 100644
--- a/gfs2/fsck/fs_recovery.c
+++ b/gfs2/fsck/fs_recovery.c
@@ -436,10 +436,9 @@ static int check_journal_seq_no(struct gfs2_inode *ip, int fix)
(unsigned long long)lowest_seq,
(unsigned long long)highest_seq,
(unsigned long long)prev_seq);
- if (!fix) {
- seq_errors++;
+ seq_errors++;
+ if (!fix)
continue;
- }
highest_seq++;
lh.lh_sequence = highest_seq;
prev_seq = lh.lh_sequence;
@@ -449,8 +448,10 @@ static int check_journal_seq_no(struct gfs2_inode *ip, int fix)
gfs2_log_header_out(&lh, bh);
brelse(bh);
}
- if (seq_errors && fix)
+ if (seq_errors && fix) {
log_err(_("%d sequence errors fixed.\n"), seq_errors);
+ seq_errors = 0;
+ }
return seq_errors;
}
9 years
gfs2-utils: RHEL7 - fsck.gfs2: Change block_map to match bitmap
by Andrew Price
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=5c82136b...
Commit: 5c82136b8b26b063542af8850c494cacb5c97c87
Parent: 6abfaa91f56f771c2ebaa6bc77d76503ac9bd899
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Fri Oct 17 11:28:20 2014 -0500
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Wed Apr 1 16:51:35 2015 +0100
fsck.gfs2: Change block_map to match bitmap
This patch changes the old block_map structure for fsck.gfs2 to the
simpler bitmap structure so that we have a 1:1 correspondence. This
was done to reduce memory requirements of fsck.gfs2.
---
gfs2/fsck/lost_n_found.c | 4 +-
gfs2/fsck/metawalk.c | 69 ++++++++-------
gfs2/fsck/metawalk.h | 6 +-
gfs2/fsck/pass1.c | 218 ++++++++++++++++++++++++++--------------------
gfs2/fsck/pass1b.c | 39 ++++----
gfs2/fsck/pass1c.c | 20 +++--
gfs2/fsck/pass2.c | 143 +++++++++++-------------------
gfs2/fsck/pass3.c | 27 +++---
gfs2/fsck/pass4.c | 15 +--
gfs2/fsck/pass5.c | 2 +-
gfs2/fsck/util.c | 59 +++++--------
gfs2/fsck/util.h | 113 ++----------------------
12 files changed, 300 insertions(+), 415 deletions(-)
diff --git a/gfs2/fsck/lost_n_found.c b/gfs2/fsck/lost_n_found.c
index b2e35e2..ba3ae1d 100644
--- a/gfs2/fsck/lost_n_found.c
+++ b/gfs2/fsck/lost_n_found.c
@@ -132,7 +132,7 @@ void make_sure_lf_exists(struct gfs2_inode *ip)
set_di_nlink(sdp->md.rooti);
q = block_type(lf_dip->i_di.di_num.no_addr);
- if (q != gfs2_inode_dir) {
+ if (q != GFS2_BLKST_DINODE) {
lf_was_created = 1;
/* This is a new lost+found directory, so set its block type
and increment link counts for the directories */
@@ -140,7 +140,7 @@ void make_sure_lf_exists(struct gfs2_inode *ip)
whether it created a new directory or just found an old one,
and we used that instead of the block_type to run this */
fsck_blockmap_set(ip, lf_dip->i_di.di_num.no_addr,
- _("lost+found dinode"), gfs2_inode_dir);
+ _("lost+found dinode"), GFS2_BLKST_DINODE);
dirtree_insert(lf_dip->i_di.di_num);
/* root inode links to lost+found */
incr_link_count(sdp->md.rooti->i_di.di_num, lf_dip, _("root"));
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index adc87a4..b679459 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -29,9 +29,9 @@
you'll get bitmap mismatches. This function checks the status of the
bitmap whenever the blockmap changes, and fixes it accordingly. */
int check_n_fix_bitmap(struct gfs2_sbd *sdp, uint64_t blk, int error_on_dinode,
- enum gfs2_mark_block new_blockmap_state)
+ int new_blockmap_state)
{
- int old_bitmap_state, new_bitmap_state;
+ int old_bitmap_state;
struct rgrp_tree *rgd;
rgd = gfs2_blk2rgrpd(sdp, blk);
@@ -43,19 +43,18 @@ int check_n_fix_bitmap(struct gfs2_sbd *sdp, uint64_t blk, int error_on_dinode,
(unsigned long long)blk, (unsigned long long)blk);
return -1;
}
- new_bitmap_state = blockmap_to_bitmap(new_blockmap_state, sdp->gfs1);
- if (old_bitmap_state != new_bitmap_state) {
+ if (old_bitmap_state != new_blockmap_state) {
const char *allocdesc[2][5] = { /* gfs2 descriptions */
{"free", "data", "unlinked", "inode", "reserved"},
/* gfs1 descriptions: */
{"free", "data", "free meta", "metadata", "reserved"}};
if (error_on_dinode && old_bitmap_state == GFS2_BLKST_DINODE &&
- new_bitmap_state != GFS2_BLKST_FREE) {
+ new_blockmap_state != GFS2_BLKST_FREE) {
log_debug(_("Reference as '%s' to block %llu (0x%llx) "
"which was marked as dinode. Needs "
"further investigation.\n"),
- allocdesc[sdp->gfs1][new_bitmap_state],
+ allocdesc[sdp->gfs1][new_blockmap_state],
(unsigned long long)blk,
(unsigned long long)blk);
return 1;
@@ -65,7 +64,7 @@ int check_n_fix_bitmap(struct gfs2_sbd *sdp, uint64_t blk, int error_on_dinode,
log_err( _("Block %llu (0x%llx) was '%s', should be %s.\n"),
(unsigned long long)blk, (unsigned long long)blk,
allocdesc[sdp->gfs1][old_bitmap_state],
- allocdesc[sdp->gfs1][new_bitmap_state]);
+ allocdesc[sdp->gfs1][new_blockmap_state]);
if (query( _("Fix the bitmap? (y/n)"))) {
/* If the new bitmap state is free (and therefore the
old state was not) we have to add to the free
@@ -74,11 +73,12 @@ int check_n_fix_bitmap(struct gfs2_sbd *sdp, uint64_t blk, int error_on_dinode,
subtract to the free space. If the type changed
from dinode to data or data to dinode, no change in
free space. */
- gfs2_set_bitmap(rgd, blk, new_bitmap_state);
- if (new_bitmap_state == GFS2_BLKST_FREE) {
+ gfs2_set_bitmap(rgd, blk, new_blockmap_state);
+ if (new_blockmap_state == GFS2_BLKST_FREE) {
/* If we're freeing a dinode, get rid of
the hash table entries for it. */
- if (old_bitmap_state == GFS2_BLKST_DINODE) {
+ if (old_bitmap_state == GFS2_BLKST_DINODE ||
+ old_bitmap_state == GFS2_BLKST_UNLINKED) {
struct dir_info *dt;
struct inode_info *ii;
@@ -114,18 +114,18 @@ int check_n_fix_bitmap(struct gfs2_sbd *sdp, uint64_t blk, int error_on_dinode,
* bitmap, and adjust free space accordingly.
*/
int _fsck_blockmap_set(struct gfs2_inode *ip, uint64_t bblock,
- const char *btype, enum gfs2_mark_block mark,
- int error_on_dinode,
- const char *caller, int fline)
+ const char *btype, int mark,
+ int error_on_dinode, const char *caller, int fline)
{
int error;
static int prev_ino_addr = 0;
- static enum gfs2_mark_block prev_mark = 0;
+ static int prev_mark = 0;
static int prevcount = 0;
+ static const char *prev_caller = NULL;
if (print_level >= MSG_DEBUG) {
if ((ip->i_di.di_num.no_addr == prev_ino_addr) &&
- (mark == prev_mark)) {
+ (mark == prev_mark) && caller == prev_caller) {
log_info("(0x%llx) ", (unsigned long long)bblock);
prevcount++;
if (prevcount > 10) {
@@ -145,7 +145,7 @@ int _fsck_blockmap_set(struct gfs2_inode *ip, uint64_t bblock,
(unsigned long long)ip->i_di.di_num.no_addr,
block_type_string(mark));
- } else if (mark == gfs2_bad_block || mark == gfs2_meta_inval) {
+ } else if (mark == GFS2_BLKST_UNLINKED) {
if (prevcount) {
log_info("\n");
prevcount = 0;
@@ -170,6 +170,7 @@ int _fsck_blockmap_set(struct gfs2_inode *ip, uint64_t bblock,
}
prev_ino_addr = ip->i_di.di_num.no_addr;
prev_mark = mark;
+ prev_caller = caller;
}
/* First, check the rgrp bitmap against what we think it should be.
@@ -909,8 +910,9 @@ static int check_eattr_entries(struct gfs2_inode *ip,
a single byte. */
fsck_blockmap_set(ip,
ip->i_di.di_eattr,
- _("extended attribute"),
- gfs2_meta_eattr);
+ _("extended attribute"),
+ sdp->gfs1 ? GFS2_BLKST_DINODE :
+ GFS2_BLKST_USED);
log_err( _("The EA was "
"fixed.\n"));
} else {
@@ -986,7 +988,7 @@ int delete_block(struct gfs2_inode *ip, uint64_t block,
void *private)
{
if (valid_block(ip->i_sbd, block)) {
- fsck_blockmap_set(ip, block, btype, gfs2_block_free);
+ fsck_blockmap_set(ip, block, btype, GFS2_BLKST_FREE);
return 0;
}
return -1;
@@ -1041,7 +1043,7 @@ static int delete_block_if_notdup(struct gfs2_inode *ip, uint64_t block,
return meta_error;
q = block_type(block);
- if (q == gfs2_block_free) {
+ if (q == GFS2_BLKST_FREE) {
log_info( _("%s block %lld (0x%llx), part of inode "
"%lld (0x%llx), was already free.\n"),
btype, (unsigned long long)block,
@@ -1060,7 +1062,7 @@ static int delete_block_if_notdup(struct gfs2_inode *ip, uint64_t block,
(unsigned long long)ip->i_di.di_num.no_addr,
(unsigned long long)block, (unsigned long long)block);
} else {
- fsck_blockmap_set(ip, block, btype, gfs2_block_free);
+ fsck_blockmap_set(ip, block, btype, GFS2_BLKST_FREE);
}
return meta_is_good;
}
@@ -1672,7 +1674,7 @@ undo_metalist:
delete_all_dups(ip);
/* Set the dinode as "bad" so it gets deleted */
fsck_blockmap_set(ip, ip->i_di.di_num.no_addr,
- _("corrupt"), gfs2_block_free);
+ _("corrupt"), GFS2_BLKST_FREE);
log_err(_("The corrupt inode was invalidated.\n"));
out:
free_metalist(ip, &metalist[0]);
@@ -1763,8 +1765,8 @@ int remove_dentry_from_dir(struct gfs2_sbd *sdp, uint64_t dir,
remove_dentry_fxns.check_dentry = remove_dentry;
q = block_type(dir);
- if (q != gfs2_inode_dir) {
- log_info( _("Parent block is not a directory...ignoring\n"));
+ if (q != GFS2_BLKST_DINODE) {
+ log_info( _("Parent block is not an inode...ignoring\n"));
return 1;
}
/* Need to run check_dir with a private var of dentryblock,
@@ -1807,7 +1809,7 @@ static int del_eattr_generic(struct gfs2_inode *ip, uint64_t block,
if (valid_block(ip->i_sbd, block)) {
q = block_type(block);
- if (q == gfs2_block_free)
+ if (q == GFS2_BLKST_FREE)
was_free = 1;
ret = delete_block_if_notdup(ip, block, NULL, eatype,
NULL, private);
@@ -1907,12 +1909,13 @@ static int alloc_metalist(struct gfs2_inode *ip, uint64_t block,
*was_duplicate = 0;
*bh = bread(ip->i_sbd, block);
q = block_type(block);
- if (blockmap_to_bitmap(q, ip->i_sbd->gfs1) == GFS2_BLKST_FREE) {
+ if (q == GFS2_BLKST_FREE) {
log_debug(_("%s reference to new metadata block "
"%lld (0x%llx) is now marked as indirect.\n"),
desc, (unsigned long long)block,
(unsigned long long)block);
- gfs2_blockmap_set(bl, block, gfs2_indir_blk);
+ gfs2_blockmap_set(bl, block, ip->i_sbd->gfs1 ?
+ GFS2_BLKST_DINODE : GFS2_BLKST_USED);
}
return meta_is_good;
}
@@ -1927,12 +1930,12 @@ static int alloc_data(struct gfs2_inode *ip, uint64_t metablock,
/* We can't check the bitmap here because this function is called
after the bitmap has been set but before the blockmap has. */
q = block_type(block);
- if (blockmap_to_bitmap(q, ip->i_sbd->gfs1) == GFS2_BLKST_FREE) {
+ if (q == GFS2_BLKST_FREE) {
log_debug(_("%s reference to new data block "
"%lld (0x%llx) is now marked as data.\n"),
desc, (unsigned long long)block,
(unsigned long long)block);
- gfs2_blockmap_set(bl, block, gfs2_block_used);
+ gfs2_blockmap_set(bl, block, GFS2_BLKST_USED);
}
return 0;
}
@@ -1945,9 +1948,10 @@ static int alloc_leaf(struct gfs2_inode *ip, uint64_t block, void *private)
/* We can't check the bitmap here because this function is called
after the bitmap has been set but before the blockmap has. */
q = block_type(block);
- if (blockmap_to_bitmap(q, ip->i_sbd->gfs1) == GFS2_BLKST_FREE)
+ if (q == GFS2_BLKST_FREE)
fsck_blockmap_set(ip, block, _("newly allocated leaf"),
- gfs2_leaf_blk);
+ ip->i_sbd->gfs1 ? GFS2_BLKST_DINODE :
+ GFS2_BLKST_USED);
return 0;
}
@@ -2119,7 +2123,8 @@ int write_new_leaf(struct gfs2_inode *dip, int start_lindex, int num_copies,
free(padbuf);
return -1;
}
- fsck_blockmap_set(dip, *bn, _("directory leaf"), gfs2_leaf_blk);
+ fsck_blockmap_set(dip, *bn, _("directory leaf"), dip->i_sbd->gfs1 ?
+ GFS2_BLKST_DINODE : GFS2_BLKST_USED);
log_err(_("A new directory leaf was allocated at block %lld "
"(0x%llx) to fill the %d (0x%x) pointer gap %s the existing "
"pointer at index %d (0x%x).\n"), (unsigned long long)*bn,
diff --git a/gfs2/fsck/metawalk.h b/gfs2/fsck/metawalk.h
index 06345c3..057e698 100644
--- a/gfs2/fsck/metawalk.h
+++ b/gfs2/fsck/metawalk.h
@@ -46,12 +46,10 @@ extern int delete_eattr_extentry(struct gfs2_inode *ip, uint64_t *ea_data_ptr,
void *private);
extern int _fsck_blockmap_set(struct gfs2_inode *ip, uint64_t bblock,
- const char *btype, enum gfs2_mark_block mark,
- int error_on_dinode,
+ const char *btype, int mark, int error_on_dinode,
const char *caller, int line);
extern int check_n_fix_bitmap(struct gfs2_sbd *sdp, uint64_t blk,
- int error_on_dinode,
- enum gfs2_mark_block new_blockmap_state);
+ int error_on_dinode, int new_blockmap_state);
extern int check_i_goal(struct gfs2_inode *ip, uint64_t goal_blk,
void *private);
extern void reprocess_inode(struct gfs2_inode *ip, const char *desc);
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index 5342701..b516a21 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -137,7 +137,7 @@ static int resuscitate_metalist(struct gfs2_inode *ip, uint64_t block,
*bh = NULL;
if (!valid_block(ip->i_sbd, block)){ /* blk outside of FS */
fsck_blockmap_set(ip, ip->i_di.di_num.no_addr,
- _("itself"), gfs2_bad_block);
+ _("itself"), GFS2_BLKST_UNLINKED);
log_err( _("Bad indirect block pointer (invalid or out of "
"range) found in system inode %lld (0x%llx).\n"),
(unsigned long long)ip->i_di.di_num.no_addr,
@@ -146,9 +146,12 @@ static int resuscitate_metalist(struct gfs2_inode *ip, uint64_t block,
return meta_is_good;
}
if (fsck_system_inode(ip->i_sbd, block))
- fsck_blockmap_set(ip, block, _("system file"), gfs2_indir_blk);
+ fsck_blockmap_set(ip, block, _("system file"),
+ ip->i_sbd->gfs1 ?
+ GFS2_BLKST_DINODE : GFS2_BLKST_USED);
else
- check_n_fix_bitmap(ip->i_sbd, block, 0, gfs2_indir_blk);
+ check_n_fix_bitmap(ip->i_sbd, block, 0, ip->i_sbd->gfs1 ?
+ GFS2_BLKST_DINODE : GFS2_BLKST_USED);
bc->indir_count++;
return meta_is_good;
}
@@ -168,7 +171,6 @@ static int resuscitate_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
struct gfs2_dirent dentry, *de;
char tmp_name[PATH_MAX];
uint64_t block;
- enum gfs2_mark_block dinode_type;
memset(&dentry, 0, sizeof(struct gfs2_dirent));
gfs2_dirent_in(&dentry, (char *)dent);
@@ -188,21 +190,15 @@ static int resuscitate_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
(unsigned long long)ip->i_di.di_num.no_addr);
return 0;
}
- if (block == sdp->md.jiinode->i_di.di_num.no_addr)
- dinode_type = gfs2_inode_dir;
- else if (!sdp->gfs1 && (block == sdp->md.pinode->i_di.di_num.no_addr ||
- block == sdp->master_dir->i_di.di_num.no_addr))
- dinode_type = gfs2_inode_dir;
- else
- dinode_type = gfs2_inode_file;
/* If this is a system dinode, we'll handle it later in
check_system_inodes. If not, it'll be handled by pass1 but
since it's in a system directory we need to make sure it's
represented in the rgrp bitmap. */
if (fsck_system_inode(sdp, block))
- fsck_blockmap_set(ip, block, _("system file"), dinode_type);
+ fsck_blockmap_set(ip, block, _("system file"),
+ GFS2_BLKST_DINODE);
else
- check_n_fix_bitmap(sdp, block, 0, dinode_type);
+ check_n_fix_bitmap(sdp, block, 0, GFS2_BLKST_DINODE);
/* Return the number of leaf entries so metawalk doesn't flag this
leaf as having none. */
*count = be16_to_cpu(((struct gfs2_leaf *)bh->b_data)->lf_entries);
@@ -225,7 +221,7 @@ static int p1check_leaf(struct gfs2_inode *ip, uint64_t block, void *private)
So we know it's a leaf block. */
bc->indir_count++;
q = block_type(block);
- if (q != gfs2_block_free) {
+ if (q != GFS2_BLKST_FREE) {
log_err( _("Found duplicate block #%llu (0x%llx) referenced "
"as a directory leaf in dinode "
"%llu (0x%llx) - was marked %d (%s)\n"),
@@ -235,12 +231,15 @@ static int p1check_leaf(struct gfs2_inode *ip, uint64_t block, void *private)
(unsigned long long)ip->i_di.di_num.no_addr, q,
block_type_string(q));
add_duplicate_ref(ip, block, ref_as_meta, 0, INODE_VALID);
- if (q == gfs2_leaf_blk) /* If the previous reference also saw
- this as a leaf, it was already
- checked, so don't check again. */
+ if (q == (ip->i_sbd->gfs1 ? GFS2_BLKST_DINODE :
+ GFS2_BLKST_USED))
+ /* If the previous reference also saw this as a leaf,
+ it was already checked, so don't check again. */
return EEXIST; /* non-fatal */
}
- fsck_blockmap_set(ip, block, _("directory leaf"), gfs2_leaf_blk);
+ fsck_blockmap_set(ip, block, _("directory leaf"),
+ ip->i_sbd->gfs1 ? GFS2_BLKST_DINODE :
+ GFS2_BLKST_USED);
return 0;
}
@@ -264,7 +263,7 @@ static int check_metalist(struct gfs2_inode *ip, uint64_t block,
set "free" and removed from the inodetree by
undo_check_metalist. */
fsck_blockmap_set(ip, ip->i_di.di_num.no_addr,
- _("bad block referencing"), gfs2_bad_block);
+ _("bad block referencing"), GFS2_BLKST_UNLINKED);
log_debug( _("Bad indirect block (invalid/out of range) "
"found in inode %lld (0x%llx).\n"),
(unsigned long long)ip->i_di.di_num.no_addr,
@@ -280,7 +279,7 @@ static int check_metalist(struct gfs2_inode *ip, uint64_t block,
blktypedesc = _("a journaled data block");
}
q = block_type(block);
- if (q != gfs2_block_free) {
+ if (q != GFS2_BLKST_FREE) {
log_err( _("Found duplicate block #%llu (0x%llx) referenced "
"as metadata in indirect block for dinode "
"%llu (0x%llx) - was marked %d (%s)\n"),
@@ -314,7 +313,8 @@ static int check_metalist(struct gfs2_inode *ip, uint64_t block,
brelse(nbh);
} else {
*bh = nbh;
- fsck_blockmap_set(ip, block, _("indirect"), gfs2_indir_blk);
+ fsck_blockmap_set(ip, block, _("indirect"), ip->i_sbd->gfs1 ?
+ GFS2_BLKST_DINODE : GFS2_BLKST_USED);
}
if (*is_valid)
@@ -342,7 +342,7 @@ static int undo_reference(struct gfs2_inode *ip, uint64_t block, int meta,
if (!valid_block(ip->i_sbd, block)) { /* blk outside of FS */
fsck_blockmap_set(ip, ip->i_di.di_num.no_addr,
- _("bad block referencing"), gfs2_block_free);
+ _("bad block referencing"), GFS2_BLKST_FREE);
return 1;
}
@@ -380,7 +380,7 @@ static int undo_reference(struct gfs2_inode *ip, uint64_t block, int meta,
}
fsck_blockmap_set(ip, block,
meta ? _("bad indirect") : _("referenced data"),
- gfs2_block_free);
+ GFS2_BLKST_FREE);
return 0;
}
@@ -410,7 +410,7 @@ static int blockmap_set_as_data(struct gfs2_inode *ip, uint64_t block)
struct gfs2_buffer_head *bh;
struct gfs2_dinode *di;
- error = fsck_blkmap_set_noino(ip, block, _("data"), gfs2_block_used);
+ error = fsck_blkmap_set_noino(ip, block, _("data"), GFS2_BLKST_USED);
if (!error)
return 0;
@@ -436,7 +436,7 @@ static int blockmap_set_as_data(struct gfs2_inode *ip, uint64_t block)
error = -1;
out:
if (!error)
- fsck_blockmap_set(ip, block, _("data"), gfs2_block_used);
+ fsck_blockmap_set(ip, block, _("data"), GFS2_BLKST_USED);
brelse(bh);
return error;
}
@@ -464,12 +464,15 @@ static int check_data(struct gfs2_inode *ip, uint64_t metablock,
* blocks later */
fsck_blockmap_set(ip, ip->i_di.di_num.no_addr,
_("bad (out of range) data"),
- gfs2_bad_block);
+ GFS2_BLKST_UNLINKED);
return -1;
}
bc->data_count++; /* keep the count sane anyway */
q = block_type(block);
- if (q != gfs2_block_free) {
+ if (q != GFS2_BLKST_FREE) {
+ struct gfs2_buffer_head *bh;
+ struct gfs2_meta_header mh;
+
log_err( _("Found duplicate %s block %llu (0x%llx) "
"referenced as data by dinode %llu (0x%llx) "),
block_type_string(q),
@@ -483,11 +486,11 @@ static int check_data(struct gfs2_inode *ip, uint64_t metablock,
log_err(_("from metadata block %llu (0x%llx)\n"),
(unsigned long long)metablock,
(unsigned long long)metablock);
-
- if (q >= gfs2_indir_blk && q <= gfs2_jdata) {
- log_info(_("The block was processed earlier as valid "
- "metadata, so it can't possibly be "
- "data.\n"));
+
+ switch (q) {
+ case GFS2_BLKST_DINODE:
+ log_info(_("The block was processed earlier as an "
+ "inode, so it can't possibly be data.\n"));
/* We still need to add a duplicate record here because
when check_metatree tries to delete the inode, we
can't have the "undo" functions freeing the block
@@ -495,8 +498,27 @@ static int check_data(struct gfs2_inode *ip, uint64_t metablock,
add_duplicate_ref(ip, block, ref_as_data, 0,
INODE_VALID);
return 1;
- }
- if (q != gfs2_meta_inval) {
+ case GFS2_BLKST_USED: /* tough decision: May be data or meta */
+ bh = bread(ip->i_sbd, block);
+ gfs2_meta_header_in(&mh, bh);
+ brelse(bh);
+ if (mh.mh_magic == GFS2_MAGIC &&
+ mh.mh_type >= GFS2_METATYPE_RG &&
+ mh.mh_type <= GFS2_METATYPE_QC &&
+ mh.mh_type != GFS2_METATYPE_DI &&
+ mh.mh_format % 100 == 0) {
+ log_info(_("The block was processed earlier "
+ "as valid metadata, so it can't "
+ "possibly be data.\n"));
+ /* We still need to add a duplicate record here
+ because when check_metatree tries to delete
+ the inode, we can't have the "undo"
+ functions freeing the block out from other
+ the original referencing inode. */
+ add_duplicate_ref(ip, block, ref_as_data, 0,
+ INODE_VALID);
+ return 1;
+ }
log_info( _("Seems to be a normal duplicate; I'll "
"sort it out in pass1b.\n"));
add_duplicate_ref(ip, block, ref_as_data, 0,
@@ -504,11 +526,12 @@ static int check_data(struct gfs2_inode *ip, uint64_t metablock,
/* This inode references the block as data. So if this
all is validated, we want to keep this count. */
return 0;
+ case GFS2_BLKST_UNLINKED:
+ log_info( _("The block was invalid as metadata but might be "
+ "okay as data. I'll sort it out in pass1b.\n"));
+ add_duplicate_ref(ip, block, ref_as_data, 0, INODE_VALID);
+ return 0;
}
- log_info( _("The block was invalid as metadata but might be "
- "okay as data. I'll sort it out in pass1b.\n"));
- add_duplicate_ref(ip, block, ref_as_data, 0, INODE_VALID);
- return 0;
}
/* In gfs1, rgrp indirect blocks are marked in the bitmap as "meta".
In gfs2, "meta" is only for dinodes. So here we dummy up the
@@ -517,13 +540,13 @@ static int check_data(struct gfs2_inode *ip, uint64_t metablock,
log_info(_("Block %lld (0x%llx) is a GFS1 rindex block\n"),
(unsigned long long)block, (unsigned long long)block);
gfs2_special_set(&gfs1_rindex_blks, block);
- fsck_blockmap_set(ip, block, _("rgrp"), gfs2_indir_blk);
+ fsck_blockmap_set(ip, block, _("rgrp"), GFS2_BLKST_DINODE);
/*gfs2_meta_rgrp);*/
} else if (ip->i_sbd->gfs1 && ip->i_di.di_flags & GFS2_DIF_JDATA) {
log_info(_("Block %lld (0x%llx) is a GFS1 journaled data "
"block\n"),
(unsigned long long)block, (unsigned long long)block);
- fsck_blockmap_set(ip, block, _("jdata"), gfs2_jdata);
+ fsck_blockmap_set(ip, block, _("jdata"), GFS2_BLKST_DINODE);
} else
return blockmap_set_as_data(ip, block);
return 0;
@@ -618,7 +641,7 @@ static int check_eattr_indir(struct gfs2_inode *ip, uint64_t indirect,
count it as a duplicate. */
*bh = bread(sdp, indirect);
if (gfs2_check_meta(*bh, GFS2_METATYPE_IN)) {
- if (q != gfs2_block_free) { /* Duplicate? */
+ if (q != GFS2_BLKST_FREE) { /* Duplicate? */
add_duplicate_ref(ip, indirect, ref_as_ea, 0,
INODE_VALID);
if (!clear_eas(ip, bc, indirect, 1,
@@ -632,7 +655,7 @@ static int check_eattr_indir(struct gfs2_inode *ip, uint64_t indirect,
"type"));
return 1;
}
- if (q != gfs2_block_free) { /* Duplicate? */
+ if (q != GFS2_BLKST_FREE) { /* Duplicate? */
log_err( _("Inode #%llu (0x%llx): Duplicate Extended "
"Attribute indirect block found at #%llu "
"(0x%llx).\n"),
@@ -645,8 +668,8 @@ static int check_eattr_indir(struct gfs2_inode *ip, uint64_t indirect,
ret = 1;
} else {
fsck_blockmap_set(ip, indirect,
- _("indirect Extended Attribute"),
- gfs2_indir_blk);
+ _("indirect Extended Attribute"), sdp->gfs1 ?
+ GFS2_BLKST_DINODE : GFS2_BLKST_USED);
bc->ea_count++;
}
return ret;
@@ -715,7 +738,7 @@ static int check_ealeaf_block(struct gfs2_inode *ip, uint64_t block, int btype,
If it isn't, clear it but don't count it as a duplicate. */
leaf_bh = bread(sdp, block);
if (gfs2_check_meta(leaf_bh, btype)) {
- if (q != gfs2_block_free) { /* Duplicate? */
+ if (q != GFS2_BLKST_FREE) { /* Duplicate? */
add_duplicate_ref(ip, block, ref_as_ea, 0,
INODE_VALID);
clear_eas(ip, bc, block, 1,
@@ -728,7 +751,7 @@ static int check_ealeaf_block(struct gfs2_inode *ip, uint64_t block, int btype,
brelse(leaf_bh);
return 1;
}
- if (q != gfs2_block_free) { /* Duplicate? */
+ if (q != GFS2_BLKST_FREE) { /* Duplicate? */
log_debug( _("Duplicate block found at #%lld (0x%llx).\n"),
(unsigned long long)block,
(unsigned long long)block);
@@ -748,9 +771,10 @@ static int check_ealeaf_block(struct gfs2_inode *ip, uint64_t block, int btype,
return 1;
}
/* Point of confusion: We've got to set the ea block itself to
- gfs2_meta_eattr here. Elsewhere we mark the inode with
+ GFS2_BLKST_USED here. Elsewhere we mark the inode with
gfs2_eattr_block meaning it contains an eattr for pass1c. */
- fsck_blockmap_set(ip, block, _("Extended Attribute"), gfs2_meta_eattr);
+ fsck_blockmap_set(ip, block, _("Extended Attribute"),
+ sdp->gfs1 ? GFS2_BLKST_DINODE : GFS2_BLKST_USED);
bc->ea_count++;
*bh = leaf_bh;
return 0;
@@ -790,7 +814,7 @@ static int check_extended_leaf_eattr(struct gfs2_inode *ip, uint64_t *data_ptr,
(unsigned long long)el_blk);
fsck_blockmap_set(ip, ip->i_di.di_eattr,
_("bad (out of range) Extended Attribute "),
- gfs2_bad_block);
+ GFS2_BLKST_UNLINKED);
return 1;
}
error = check_ealeaf_block(ip, el_blk, GFS2_METATYPE_ED, &bh, private);
@@ -831,7 +855,7 @@ static int check_eattr_leaf(struct gfs2_inode *ip, uint64_t block,
(unsigned long long)block, (unsigned long long)block);
fsck_blockmap_set(ip, ip->i_di.di_eattr,
_("bad (out of range) Extended "
- "Attribute leaf"), gfs2_bad_block);
+ "Attribute leaf"), GFS2_BLKST_UNLINKED);
return 1;
}
return check_ealeaf_block(ip, block, GFS2_METATYPE_EA, bh, private);
@@ -910,7 +934,7 @@ static int mark_block_invalid(struct gfs2_inode *ip, uint64_t block,
}
q = block_type(block);
- if (q != gfs2_block_free) {
+ if (q != GFS2_BLKST_FREE) {
if (was_duplicate)
*was_duplicate = 1;
add_duplicate_ref(ip, block, reftype, 0, INODE_INVALID);
@@ -923,7 +947,7 @@ static int mark_block_invalid(struct gfs2_inode *ip, uint64_t block,
(unsigned long long)ip->i_di.di_num.no_addr);
return meta_is_good;
}
- fsck_blockmap_set(ip, block, btype, gfs2_meta_inval);
+ fsck_blockmap_set(ip, block, btype, GFS2_BLKST_UNLINKED);
return meta_is_good;
}
@@ -1008,7 +1032,7 @@ static int rangecheck_block(struct gfs2_inode *ip, uint64_t block,
}
/* See how many duplicate blocks it has */
q = block_type(block);
- if (q != gfs2_block_free) {
+ if (q != GFS2_BLKST_FREE) {
(*bad_pointers)++;
log_info( _("Duplicated %s block pointer (violation %ld, block"
" %lld (0x%llx)) found in inode %lld (0x%llx).\n"),
@@ -1100,7 +1124,7 @@ static int handle_ip(struct gfs2_sbd *sdp, struct gfs2_inode *ip)
(unsigned long long)ip->i_di.di_num.no_addr,
BAD_POINTER_TOLERANCE);
fsck_blockmap_set(ip, ip->i_di.di_num.no_addr,
- _("badly corrupt"), gfs2_block_free);
+ _("badly corrupt"), GFS2_BLKST_FREE);
return 0;
}
@@ -1113,7 +1137,7 @@ static int handle_ip(struct gfs2_sbd *sdp, struct gfs2_inode *ip)
metadata will be flagged as metadata or data blocks yet.
Therefore, we don't need to invalidate anything. */
fsck_blockmap_set(ip, ip->i_di.di_num.no_addr,
- _("invalid mode"), gfs2_block_free);
+ _("invalid mode"), GFS2_BLKST_FREE);
return 0;
} else if (error)
goto bad_dinode;
@@ -1241,8 +1265,7 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh,
static int check_system_inode(struct gfs2_sbd *sdp,
struct gfs2_inode **sysinode,
const char *filename,
- int builder(struct gfs2_sbd *sdp),
- enum gfs2_mark_block mark,
+ int builder(struct gfs2_sbd *sdp), int isdir,
struct gfs2_inode *sysdir, int needs_sysbit)
{
uint64_t iblock = 0;
@@ -1263,8 +1286,8 @@ static int check_system_inode(struct gfs2_sbd *sdp,
"%llu (0x%llx)\n"),
(unsigned long long)iblock,
(unsigned long long)iblock);
- gfs2_blockmap_set(bl, iblock, gfs2_block_free);
- check_n_fix_bitmap(sdp, iblock, 0, gfs2_block_free);
+ gfs2_blockmap_set(bl, iblock, GFS2_BLKST_FREE);
+ check_n_fix_bitmap(sdp, iblock, 0, GFS2_BLKST_FREE);
inode_put(sysinode);
}
}
@@ -1274,14 +1297,14 @@ static int check_system_inode(struct gfs2_sbd *sdp,
be recovering from a corrupt bitmap. In that case, don't
rebuild the inode. Just reuse the inode and fix the
bitmap. */
- if (ds.q == gfs2_block_free) {
+ if (ds.q == GFS2_BLKST_FREE) {
log_info( _("The inode exists but the block is not "
"marked 'in use'; fixing it.\n"));
fsck_blockmap_set(*sysinode,
(*sysinode)->i_di.di_num.no_addr,
- filename, mark);
- ds.q = mark;
- if (mark == gfs2_inode_dir)
+ filename, GFS2_BLKST_DINODE);
+ ds.q = GFS2_BLKST_DINODE;
+ if (isdir)
dirtree_insert((*sysinode)->i_di.di_num);
}
/* Make sure it's marked as a system file/directory */
@@ -1297,7 +1320,7 @@ static int check_system_inode(struct gfs2_sbd *sdp,
/* Set the blockmap (but not bitmap) back to
'free' so that it gets checked like any
normal dinode. */
- gfs2_blockmap_set(bl, iblock, gfs2_block_free);
+ gfs2_blockmap_set(bl, iblock, GFS2_BLKST_FREE);
log_err( _("Removed system inode \"%s\".\n"),
filename);
}
@@ -1309,11 +1332,11 @@ static int check_system_inode(struct gfs2_sbd *sdp,
inode and get it all setup - of course, everything will be in
lost+found then, but we *need* our system inodes before we can
do any of that. */
- if (!(*sysinode) || ds.q != mark) {
- log_err( _("Invalid or missing %s system inode (should be "
- "'%s', is '%s').\n"), filename,
- block_type_string(mark),
- block_type_string(ds.q));
+ if (!(*sysinode) || ds.q != GFS2_BLKST_DINODE) {
+ log_err(_("Invalid or missing %s system inode (is '%s', "
+ "should be '%s').\n"), filename,
+ block_type_string(ds.q),
+ block_type_string(GFS2_BLKST_DINODE));
if (query(_("Create new %s system inode? (y/n) "), filename)) {
log_err( _("Rebuilding system file \"%s\"\n"),
filename);
@@ -1328,9 +1351,9 @@ static int check_system_inode(struct gfs2_sbd *sdp,
ji_update(sdp);
fsck_blockmap_set(*sysinode,
(*sysinode)->i_di.di_num.no_addr,
- filename, mark);
- ds.q = mark;
- if (mark == gfs2_inode_dir)
+ filename, GFS2_BLKST_DINODE);
+ ds.q = GFS2_BLKST_DINODE;
+ if (isdir)
dirtree_insert((*sysinode)->i_di.di_num);
} else {
log_err( _("Cannot continue without valid %s inode\n"),
@@ -1389,10 +1412,9 @@ static int check_system_inodes(struct gfs2_sbd *sdp)
if (!sdp->gfs1) {
fsck_blockmap_set(sdp->master_dir,
sdp->master_dir->i_di.di_num.no_addr,
- "master", gfs2_inode_dir);
+ "master", GFS2_BLKST_DINODE);
if (check_system_inode(sdp, &sdp->master_dir, "master",
- build_master, gfs2_inode_dir,
- NULL, 1)) {
+ build_master, 1, NULL, 1)) {
stack;
return -1;
}
@@ -1400,43 +1422,42 @@ static int check_system_inodes(struct gfs2_sbd *sdp)
/* Mark the root dinode as a "dinode" in the block map as we did
for master, since it has no parent. */
fsck_blockmap_set(sdp->md.rooti, sdp->md.rooti->i_di.di_num.no_addr,
- "root", gfs2_inode_dir);
- if (check_system_inode(sdp, &sdp->md.rooti, "root", build_root,
- gfs2_inode_dir, NULL, 0)) {
+ "root", GFS2_BLKST_DINODE);
+ if (check_system_inode(sdp, &sdp->md.rooti, "root", build_root, 1,
+ NULL, 0)) {
stack;
return -1;
}
if (!sdp->gfs1 &&
- check_system_inode(sdp, &sdp->md.inum, "inum", build_inum,
- gfs2_inode_file, sdp->master_dir, 1)) {
+ check_system_inode(sdp, &sdp->md.inum, "inum", build_inum, 0,
+ sdp->master_dir, 1)) {
stack;
return -1;
}
- if (check_system_inode(sdp, &sdp->md.statfs, "statfs", build_statfs,
- gfs2_inode_file, sdp->master_dir, !sdp->gfs1)) {
+ if (check_system_inode(sdp, &sdp->md.statfs, "statfs", build_statfs, 0,
+ sdp->master_dir, !sdp->gfs1)) {
stack;
return -1;
}
if (check_system_inode(sdp, &sdp->md.jiinode, "jindex", build_jindex,
- (sdp->gfs1 ? gfs2_inode_file : gfs2_inode_dir),
- sdp->master_dir, !sdp->gfs1)) {
+ (sdp->gfs1 ? 0 : 1), sdp->master_dir,
+ !sdp->gfs1)) {
stack;
return -1;
}
if (check_system_inode(sdp, &sdp->md.riinode, "rindex", build_rindex,
- gfs2_inode_file, sdp->master_dir, !sdp->gfs1)) {
+ 0, sdp->master_dir, !sdp->gfs1)) {
stack;
return -1;
}
if (check_system_inode(sdp, &sdp->md.qinode, "quota", build_quota,
- gfs2_inode_file, sdp->master_dir, !sdp->gfs1)) {
+ 0, sdp->master_dir, !sdp->gfs1)) {
stack;
return -1;
}
if (!sdp->gfs1 &&
check_system_inode(sdp, &sdp->md.pinode, "per_node",
- build_per_node, gfs2_inode_dir,
- sdp->master_dir, 1)) {
+ build_per_node, 1, sdp->master_dir, 1)) {
stack;
return -1;
}
@@ -1464,8 +1485,8 @@ static int check_system_inodes(struct gfs2_sbd *sdp)
sprintf(jname, "journal%d", sdp->md.journals);
if (check_system_inode(sdp, &sdp->md.journal[sdp->md.journals],
- jname, build_a_journal,
- gfs2_inode_file, sdp->md.jiinode, 1)) {
+ jname, build_a_journal, 0,
+ sdp->md.jiinode, 1)) {
stack;
return -1;
}
@@ -1529,7 +1550,7 @@ static int pass1_process_bitmap(struct gfs2_sbd *sdp, struct rgrp_tree *rgd, uin
(bh->b_data))->mh_magic;
q = block_type(block);
- if (q != gfs2_block_free) {
+ if (q != GFS2_BLKST_FREE) {
if (be32_to_cpu(check_magic) == GFS2_MAGIC &&
sdp->gfs1 && !is_inode) {
log_debug(_("Block 0x%llx assumed to be "
@@ -1580,7 +1601,7 @@ static int pass1_process_bitmap(struct gfs2_sbd *sdp, struct rgrp_tree *rgd, uin
"%llu (0x%llx)\n"),
(unsigned long long)block,
(unsigned long long)block);
- check_n_fix_bitmap(sdp, block, 0, gfs2_block_free);
+ check_n_fix_bitmap(sdp, block, 0, GFS2_BLKST_FREE);
} else if (handle_di(sdp, bh, rgd) < 0) {
stack;
brelse(bh);
@@ -1615,6 +1636,8 @@ static int pass1_process_rgrp(struct gfs2_sbd *sdp, struct rgrp_tree *rgd)
return ret;
}
+ if (fsck_abort)
+ return 0;
/*
For GFS1, we have to count the "free meta" blocks in the
resource group and mark them specially so we can count them
@@ -1624,8 +1647,11 @@ static int pass1_process_rgrp(struct gfs2_sbd *sdp, struct rgrp_tree *rgd)
continue;
n = lgfs2_bm_scan(rgd, k, ibuf, GFS2_BLKST_UNLINKED);
- for (i = 0; i < n; i++)
- gfs2_blockmap_set(bl, ibuf[i], gfs2_freemeta);
+ for (i = 0; i < n; i++) {
+ gfs2_blockmap_set(bl, ibuf[i], GFS2_BLKST_UNLINKED);
+ if (fsck_abort)
+ return 0;
+ }
}
free(ibuf);
@@ -1674,6 +1700,8 @@ int pass1(struct gfs2_sbd *sdp)
* things - we can change the method later if necessary.
*/
for (n = osi_first(&sdp->rgtree); n; n = next, rg_count++) {
+ if (fsck_abort)
+ return FSCK_CANCELED;
next = osi_next(n);
log_debug( _("Checking metadata in Resource Group #%llu\n"),
(unsigned long long)rg_count);
@@ -1683,7 +1711,7 @@ int pass1(struct gfs2_sbd *sdp)
"is now marked as 'rgrp data'\n"),
rgd->ri.ri_addr + i, rgd->ri.ri_addr + i);
if (gfs2_blockmap_set(bl, rgd->ri.ri_addr + i,
- gfs2_indir_blk)) {
+ GFS2_BLKST_USED)) {
stack;
gfs2_special_free(&gfs1_rindex_blks);
return FSCK_ERROR;
diff --git a/gfs2/fsck/pass1b.c b/gfs2/fsck/pass1b.c
index f82f43b..a8f3d28 100644
--- a/gfs2/fsck/pass1b.c
+++ b/gfs2/fsck/pass1b.c
@@ -52,7 +52,6 @@ static void log_inode_reference(struct duptree *dt, osi_list_t *tmp, int inval)
(unsigned long long)dt->block, reftypestring);
}
-/* delete_all_dups - delete all duplicate records for a given inode */
/*
* resolve_dup_references - resolve all but the last dinode that has a
* duplicate reference to a given block.
@@ -114,7 +113,7 @@ static void resolve_dup_references(struct gfs2_sbd *sdp, struct duptree *dt,
!found_good_ref) { /* We haven't found a good reference */
/* If this is an invalid inode, but not on the invalid
list, it's better to delete it. */
- if (q != gfs2_inode_invalid) {
+ if (q == GFS2_BLKST_DINODE) {
found_good_ref = 1;
log_warn( _("Inode %s (%lld/0x%llx)'s "
"reference to block %llu (0x%llx) "
@@ -158,7 +157,7 @@ static void resolve_dup_references(struct gfs2_sbd *sdp, struct duptree *dt,
dup_listent_delete(dt, id);
continue;
}
- if (q == gfs2_block_free)
+ if (q == GFS2_BLKST_FREE)
log_warn( _("Inode %lld (0x%llx) was previously "
"deleted.\n"),
(unsigned long long)id->block_no,
@@ -172,7 +171,7 @@ static void resolve_dup_references(struct gfs2_sbd *sdp, struct duptree *dt,
/* If we've already deleted this dinode, don't try to delete
it again. That could free blocks that used to be duplicate
references that are now resolved (and gone). */
- if (q != gfs2_block_free) {
+ if (q != GFS2_BLKST_FREE) {
/* Clear the EAs for the inode first */
check_inode_eattr(ip, &pass1b_fxns_delete);
/* If the reference was as metadata or data, we've got
@@ -185,7 +184,7 @@ static void resolve_dup_references(struct gfs2_sbd *sdp, struct duptree *dt,
inodetree_delete(ii);
fsck_blockmap_set(ip, ip->i_di.di_num.no_addr,
_("duplicate referencing bad"),
- gfs2_inode_invalid);
+ GFS2_BLKST_UNLINKED);
/* We delete the dup_handler inode count and
duplicate id BEFORE clearing the metadata,
because if this is the last reference to
@@ -391,7 +390,7 @@ static int handle_dup_blk(struct gfs2_sbd *sdp, struct duptree *dt)
ip = fsck_load_inode(sdp, id->block_no);
q = block_type(id->block_no);
- if (q == gfs2_inode_invalid) {
+ if (q == GFS2_BLKST_UNLINKED) {
log_debug( _("The remaining reference inode %lld "
"(0x%llx) is marked invalid: Marking "
"the block as free.\n"),
@@ -399,28 +398,32 @@ static int handle_dup_blk(struct gfs2_sbd *sdp, struct duptree *dt)
(unsigned long long)id->block_no);
fsck_blockmap_set(ip, dt->block,
_("reference-repaired leaf"),
- gfs2_block_free);
+ GFS2_BLKST_FREE);
} else if (id->reftypecount[ref_is_inode]) {
set_ip_blockmap(ip, 0); /* 0=do not add to dirtree */
} else if (id->reftypecount[ref_as_data]) {
fsck_blockmap_set(ip, dt->block,
_("reference-repaired data"),
- gfs2_block_used);
+ GFS2_BLKST_USED);
} else if (id->reftypecount[ref_as_meta]) {
if (is_dir(&ip->i_di, sdp->gfs1))
fsck_blockmap_set(ip, dt->block,
_("reference-repaired leaf"),
- gfs2_leaf_blk);
+ sdp->gfs1 ?
+ GFS2_BLKST_DINODE :
+ GFS2_BLKST_USED);
else
fsck_blockmap_set(ip, dt->block,
_("reference-repaired "
- "indirect"),
- gfs2_indir_blk);
+ "indirect"), sdp->gfs1 ?
+ GFS2_BLKST_DINODE :
+ GFS2_BLKST_USED);
} else
fsck_blockmap_set(ip, dt->block,
_("reference-repaired extended "
"attribute"),
- gfs2_meta_eattr);
+ sdp->gfs1 ? GFS2_BLKST_DINODE :
+ GFS2_BLKST_USED);
fsck_inode_put(&ip); /* out, brelse, free */
log_debug(_("Done with duplicate reference to block 0x%llx\n"),
(unsigned long long)dt->block);
@@ -441,8 +444,8 @@ static int handle_dup_blk(struct gfs2_sbd *sdp, struct duptree *dt)
if (dh.dt)
dup_delete(dh.dt);
/* Now fix the block type of the block in question. */
- gfs2_blockmap_set(bl, dup_blk, gfs2_block_free);
- check_n_fix_bitmap(sdp, dup_blk, 0, gfs2_block_free);
+ gfs2_blockmap_set(bl, dup_blk, GFS2_BLKST_FREE);
+ check_n_fix_bitmap(sdp, dup_blk, 0, GFS2_BLKST_FREE);
}
}
return 0;
@@ -599,13 +602,11 @@ int pass1b(struct gfs2_sbd *sdp)
}
q = block_type(i);
- if (q < gfs2_inode_dir)
- continue;
- if (q > gfs2_inode_invalid)
+ if (q == GFS2_BLKST_FREE || q == GFS2_BLKST_USED)
continue;
- if (q == gfs2_inode_invalid)
- log_debug( _("Checking invalidated duplicate dinode "
+ if (q == GFS2_BLKST_UNLINKED)
+ log_debug( _("Checking invalidated duplicate block "
"%lld (0x%llx)\n"),
(unsigned long long)i,
(unsigned long long)i);
diff --git a/gfs2/fsck/pass1c.c b/gfs2/fsck/pass1c.c
index ce9ca96..aa905da 100644
--- a/gfs2/fsck/pass1c.c
+++ b/gfs2/fsck/pass1c.c
@@ -97,7 +97,7 @@ static int check_eattr_indir(struct gfs2_inode *ip, uint64_t block,
return ask_remove_eattr(ip);
}
q = block_type(block);
- if (q != gfs2_indir_blk) {
+ if (q != (sdp->gfs1 ? GFS2_BLKST_DINODE : GFS2_BLKST_USED)) {
log_err( _("Extended attributes indirect block #%llu"
" (0x%llx) for inode #%llu"
" (0x%llx) is invalid.\n"),
@@ -122,16 +122,18 @@ static int check_eattr_leaf(struct gfs2_inode *ip, uint64_t block,
uint8_t q;
if (!valid_block(sdp, block)) {
- log_err( _("Extended attributes block for inode #%llu"
- " (0x%llx) is invalid.\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
+ log_err( _("Extended attributes block %lld (0x%llx) for "
+ "inode #%llu (0x%llx) is invalid.\n"),
+ (unsigned long long)block, (unsigned long long)block,
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)ip->i_di.di_num.no_addr);
return ask_remove_eattr(ip);
}
q = block_type(block);
- if (q != gfs2_meta_eattr) {
- log_err( _("Extended attributes block for inode #%llu"
- " (0x%llx) invalid.\n"),
+ if (q != (sdp->gfs1 ? GFS2_BLKST_DINODE : GFS2_BLKST_USED)) {
+ log_err( _("Extended attributes block %lld (0x%llx) for "
+ "inode #%llu (0x%llx) invalid.\n"),
+ (unsigned long long)block, (unsigned long long)block,
(unsigned long long)ip->i_di.di_num.no_addr,
(unsigned long long)ip->i_di.di_num.no_addr);
return ask_remove_eattr(ip);
@@ -218,7 +220,7 @@ static int check_eattr_extentry(struct gfs2_inode *ip, uint64_t *ea_ptr,
struct gfs2_sbd *sdp = ip->i_sbd;
q = block_type(be64_to_cpu(*ea_ptr));
- if (q != gfs2_meta_eattr) {
+ if (q != (sdp->gfs1 ? GFS2_BLKST_DINODE : GFS2_BLKST_USED)) {
if (remove_eattr_entry(sdp, leaf_bh, ea_hdr, ea_hdr_prev)){
stack;
return -1;
diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c
index 74bcc26..1d32335 100644
--- a/gfs2/fsck/pass2.c
+++ b/gfs2/fsck/pass2.c
@@ -135,40 +135,28 @@ static const char *de_type_string(uint8_t de_type)
return de_types[3]; /* invalid */
}
-static int check_file_type(uint8_t de_type, uint8_t blk_type, int gfs1)
+static int check_file_type(uint64_t block, uint8_t de_type, uint8_t q,
+ int gfs1, int *isdir)
{
- switch(blk_type) {
- case gfs2_inode_dir:
- if (de_type != (gfs1 ? GFS_FILE_DIR : DT_DIR))
- return 1;
- break;
- case gfs2_inode_file:
- if (de_type != (gfs1 ? GFS_FILE_REG : DT_REG))
- return 1;
- break;
- case gfs2_inode_lnk:
- if (de_type != (gfs1 ? GFS_FILE_LNK : DT_LNK))
- return 1;
- break;
- case gfs2_inode_device:
- if ((de_type != (gfs1 ? GFS_FILE_BLK : DT_BLK)) &&
- (de_type != (gfs1 ? GFS_FILE_CHR : DT_CHR)))
- return 1;
- break;
- case gfs2_inode_fifo:
- if (de_type != (gfs1 ? GFS_FILE_FIFO : DT_FIFO))
- return 1;
- break;
- case gfs2_inode_sock:
- if (de_type != (gfs1 ? GFS_FILE_SOCK : DT_SOCK))
- return 1;
- break;
- default:
+ struct dir_info *dt;
+
+ *isdir = 0;
+ if (q != GFS2_BLKST_DINODE) {
log_err( _("Invalid block type\n"));
return -1;
- break;
}
- return 0;
+ if (de_type == (gfs1 ? GFS_FILE_DIR : DT_DIR))
+ *isdir = 1;
+ /* Check if the dinode is in the dir tree */
+ dt = dirtree_find(block);
+ /* This is a bit confusing, so let me explain:
+ If the dirent says the inode supposed to be for a directory,
+ it should be in the dir tree. If it is, no problem, return 0.
+ If it's not, return 1 (wrong type). If it's not supposed to be
+ a directory, it shouldn't be in the dir tree. */
+ if (dt)
+ return !(*isdir);
+ return *isdir;
}
struct metawalk_fxns pass2_fxns_delete = {
@@ -209,7 +197,7 @@ static int bad_formal_ino(struct gfs2_inode *ip, struct gfs2_dirent *dent,
(unsigned long long)entry.no_formal_ino,
(unsigned long long)ii->di_num.no_formal_ino,
(unsigned long long)ii->di_num.no_formal_ino);
- if (q != gfs2_inode_dir || !strcmp("..", tmp_name)) {
+ if (q != GFS2_BLKST_DINODE || !strcmp("..", tmp_name)) {
if (query( _("Remove the corrupt directory entry? (y/n) ")))
return 1;
log_err( _("Corrupt directory entry not removed.\n"));
@@ -388,7 +376,8 @@ static int wrong_leaf(struct gfs2_inode *ip, struct gfs2_inum *entry,
(unsigned long long)real_leaf,
(unsigned long long)ip->i_di.di_blocks);
fsck_blockmap_set(ip, real_leaf, _("split leaf"),
- gfs2_indir_blk);
+ sdp->gfs1 ? GFS2_BLKST_DINODE :
+ GFS2_BLKST_USED);
}
/* If the misplaced dirent was supposed to be earlier in the
hash table, we need to adjust our counts for the blocks
@@ -449,7 +438,7 @@ static int basic_dentry_checks(struct gfs2_inode *ip, struct gfs2_dirent *dent,
struct gfs2_inum *entry, const char *tmp_name,
uint32_t *count, struct gfs2_dirent *de,
struct dir_status *ds, uint8_t *q,
- struct gfs2_buffer_head *bh)
+ struct gfs2_buffer_head *bh, int *isdir)
{
struct gfs2_sbd *sdp = ip->i_sbd;
uint32_t calculated_hash;
@@ -457,6 +446,7 @@ static int basic_dentry_checks(struct gfs2_inode *ip, struct gfs2_dirent *dent,
int error;
struct inode_info *ii;
+ *isdir = 0;
if (!valid_block(ip->i_sbd, entry->no_addr)) {
log_err( _("Block # referenced by directory entry %s in inode "
"%lld (0x%llx) is invalid\n"),
@@ -487,7 +477,7 @@ static int basic_dentry_checks(struct gfs2_inode *ip, struct gfs2_dirent *dent,
/* Don't be tempted to do this:
fsck_blockmap_set(ip, ip->i_di.di_num.no_addr,
_("corrupt directory entry"),
- gfs2_inode_invalid);
+ GFS2_BLKST_FREE);
We can't free it because another dir may have a valid reference
to it. Just return 1 so we can delete the bad dirent. */
log_err( _("Bad directory entry deleted.\n"));
@@ -530,41 +520,7 @@ static int basic_dentry_checks(struct gfs2_inode *ip, struct gfs2_dirent *dent,
* 2. Blocks marked "bad" need to have their entire
* metadata tree deleted.
*/
- if (*q == gfs2_inode_invalid || *q == gfs2_bad_block) {
- /* This entry's inode has bad blocks in it */
-
- /* Handle bad blocks */
- log_err( _("Found directory entry '%s' pointing to invalid "
- "block %lld (0x%llx)\n"), tmp_name,
- (unsigned long long)entry->no_addr,
- (unsigned long long)entry->no_addr);
-
- if (!query( _("Delete inode containing bad blocks? (y/n)"))) {
- log_warn( _("Entry to inode containing bad blocks remains\n"));
- return 0;
- }
-
- if (*q == gfs2_bad_block) {
- if (ip->i_di.di_num.no_addr == entry->no_addr)
- entry_ip = ip;
- else
- entry_ip = fsck_load_inode(sdp, entry->no_addr);
- if (ip->i_di.di_eattr) {
- check_inode_eattr(entry_ip,
- &pass2_fxns_delete);
- }
- check_metatree(entry_ip, &pass2_fxns_delete);
- if (entry_ip != ip)
- fsck_inode_put(&entry_ip);
- }
- fsck_blockmap_set(ip, entry->no_addr,
- _("bad directory entry"), gfs2_block_free);
- log_err( _("Inode %lld (0x%llx) was deleted.\n"),
- (unsigned long long)entry->no_addr,
- (unsigned long long)entry->no_addr);
- return 1;
- }
- if (*q < gfs2_inode_dir || *q > gfs2_inode_sock) {
+ if (*q != GFS2_BLKST_DINODE) {
log_err( _("Directory entry '%s' referencing inode %llu "
"(0x%llx) in dir inode %llu (0x%llx) block type "
"%d: %s.\n"), tmp_name,
@@ -572,7 +528,7 @@ static int basic_dentry_checks(struct gfs2_inode *ip, struct gfs2_dirent *dent,
(unsigned long long)entry->no_addr,
(unsigned long long)ip->i_di.di_num.no_addr,
(unsigned long long)ip->i_di.di_num.no_addr,
- *q, *q == gfs2_inode_invalid ?
+ *q, *q == GFS2_BLKST_FREE ?
_("was previously marked invalid") :
_("was deleted or is not an inode"));
@@ -601,7 +557,8 @@ static int basic_dentry_checks(struct gfs2_inode *ip, struct gfs2_dirent *dent,
return 1;
}
- error = check_file_type(de->de_type, *q, sdp->gfs1);
+ error = check_file_type(entry->no_addr, de->de_type, *q, sdp->gfs1,
+ isdir);
if (error < 0) {
log_err( _("Error: directory entry type is "
"incompatible with block type at block %lld "
@@ -674,6 +631,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
struct gfs2_dirent dentry, *de;
int hash_index; /* index into the hash table based on the hash */
int lindex_max; /* largest acceptable hash table index for hash */
+ int isdir;
memset(&dentry, 0, sizeof(struct gfs2_dirent));
gfs2_dirent_in(&dentry, (char *)dent);
@@ -690,7 +648,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
strncpy(tmp_name, filename, MAX_FILENAME - 1);
error = basic_dentry_checks(ip, dent, &entry, tmp_name, count, de,
- ds, &q, bh);
+ ds, &q, bh, &isdir);
if (error)
goto nuke_dentry;
@@ -781,8 +739,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
goto nuke_dentry;
}
-
- if (q != gfs2_inode_dir) {
+ if (!isdir) {
log_err( _("Found '..' entry in directory %llu (0x%llx) "
"pointing to something that's not a directory"),
(unsigned long long)ip->i_di.di_num.no_addr,
@@ -831,7 +788,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
}
/* After this point we're only concerned with directories */
- if (q != gfs2_inode_dir) {
+ if (!isdir) {
log_debug( _("Found non-dir inode dentry pointing to %lld "
"(0x%llx)\n"),
(unsigned long long)entry.no_addr,
@@ -916,7 +873,8 @@ static void pad_with_leafblks(struct gfs2_inode *ip, uint64_t *tbl,
(unsigned long long)new_leaf_blk,
lindex, lindex, new_len);
fsck_blockmap_set(ip, new_leaf_blk, _("pad leaf"),
- gfs2_leaf_blk);
+ ip->i_sbd->gfs1 ?
+ GFS2_BLKST_DINODE : GFS2_BLKST_USED);
/* Fix the hash table in memory to have the new leaf */
for (i = 0; i < new_len; i++)
tbl[lindex + i] = cpu_to_be64(new_leaf_blk);
@@ -941,6 +899,7 @@ static int lost_leaf(struct gfs2_inode *ip, uint64_t *tbl, uint64_t leafno,
char *bh_end = bh->b_data + ip->i_sbd->bsize;
struct gfs2_dirent de, *dent;
int error;
+ int isdir = 0;
log_err(_("Leaf block %llu (0x%llx) seems to be out of place and its "
"contents need to be moved to lost+found.\n"),
@@ -979,7 +938,7 @@ static int lost_leaf(struct gfs2_inode *ip, uint64_t *tbl, uint64_t leafno,
error = basic_dentry_checks(ip, dent, &de.de_inum,
tmp_name, &count, &de,
- &ds, &q, bh);
+ &ds, &q, bh, &isdir);
if (error) {
log_err(_("Not relocating corrupt entry "
"\"%s\".\n"), tmp_name);
@@ -999,7 +958,7 @@ static int lost_leaf(struct gfs2_inode *ip, uint64_t *tbl, uint64_t leafno,
_("from lost+found"));
/* If it's a directory, lost+found is
back-linked to it via .. */
- if (q == gfs2_inode_dir)
+ if (isdir)
incr_link_count(lf_dip->i_di.di_num,
NULL,
_("to lost+found"));
@@ -1017,7 +976,7 @@ static int lost_leaf(struct gfs2_inode *ip, uint64_t *tbl, uint64_t leafno,
log_err(_("Directory entries from misplaced leaf block were relocated "
"to lost+found.\n"));
/* Free the lost leaf. */
- fsck_blockmap_set(ip, leafno, _("lost leaf"), gfs2_block_free);
+ fsck_blockmap_set(ip, leafno, _("lost leaf"), GFS2_BLKST_FREE);
ip->i_di.di_blocks--;
bmodified(ip->i_bh);
/* Now we have to deal with the bad hash table entries pointing to the
@@ -1039,6 +998,7 @@ static int basic_check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
struct dir_status *ds = (struct dir_status *) priv;
struct gfs2_dirent dentry, *de;
int error;
+ int isdir;
memset(&dentry, 0, sizeof(struct gfs2_dirent));
gfs2_dirent_in(&dentry, (char *)dent);
@@ -1055,7 +1015,7 @@ static int basic_check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
strncpy(tmp_name, filename, MAX_FILENAME - 1);
error = basic_dentry_checks(ip, dent, &entry, tmp_name, count, de,
- ds, &q, bh);
+ ds, &q, bh, &isdir);
if (error) {
dirent2_del(ip, bh, prev_de, dent);
log_err( _("Bad directory entry '%s' cleared.\n"), tmp_name);
@@ -1248,7 +1208,8 @@ static int fix_hashtable(struct gfs2_inode *ip, uint64_t *tbl, unsigned hsize,
(unsigned long long)new_leaf_blk,
(unsigned long long)new_leaf_blk, lindex, lindex);
fsck_blockmap_set(ip, new_leaf_blk, _("split leaf"),
- gfs2_leaf_blk);
+ ip->i_sbd->gfs1 ?
+ GFS2_BLKST_DINODE : GFS2_BLKST_USED);
log_err(_("Hash table repaired.\n"));
/* Fix up the hash table in memory to include the new leaf */
for (i = 0; i < *proper_len; i++)
@@ -1712,7 +1673,7 @@ build_it:
log_err(_("Error rebuilding %s.\n"), fn);
return -1;
}
- fsck_blockmap_set(ip, ip->i_di.di_num.no_addr, fn, gfs2_inode_file);
+ fsck_blockmap_set(ip, ip->i_di.di_num.no_addr, fn, GFS2_BLKST_DINODE);
reprocess_inode(ip, fn);
log_err(_("System file %s rebuilt.\n"), fn);
goto out_good;
@@ -1740,7 +1701,7 @@ static int check_system_dir(struct gfs2_inode *sysinode, const char *dirname,
ds.q = block_type(iblock);
pass2_fxns.private = (void *) &ds;
- if (ds.q == gfs2_bad_block) {
+ if (ds.q == GFS2_BLKST_UNLINKED) {
astate_save(sysinode, &as);
/* First check that the directory's metatree is valid */
error = check_metatree(sysinode, &pass2_fxns);
@@ -1759,8 +1720,7 @@ static int check_system_dir(struct gfs2_inode *sysinode, const char *dirname,
return -1;
}
if (error > 0)
- fsck_blockmap_set(sysinode, iblock, dirname,
- gfs2_inode_invalid);
+ fsck_blockmap_set(sysinode, iblock, dirname, GFS2_BLKST_FREE);
if (check_inode_eattr(sysinode, &pass2_fxns)) {
stack;
@@ -1866,6 +1826,7 @@ int pass2(struct gfs2_sbd *sdp)
struct dir_status ds = {0};
struct gfs2_inode *ip;
int error = 0;
+ struct dir_info *dt;
/* Check all the system directory inodes. */
if (!sdp->gfs1 &&
@@ -1908,7 +1869,11 @@ int pass2(struct gfs2_sbd *sdp)
q = block_type(dirblk);
- if (q != gfs2_inode_dir)
+ if (q != GFS2_BLKST_DINODE)
+ continue;
+
+ dt = dirtree_find(dirblk);
+ if (dt == NULL)
continue;
/* If we created lost+found, its links should have been
@@ -1924,7 +1889,7 @@ int pass2(struct gfs2_sbd *sdp)
memset(&ds, 0, sizeof(ds));
pass2_fxns.private = (void *) &ds;
- if (ds.q == gfs2_bad_block) {
+ if (ds.q == GFS2_BLKST_UNLINKED) {
/* First check that the directory's metatree
* is valid */
ip = fsck_load_inode(sdp, dirblk);
@@ -1985,8 +1950,8 @@ int pass2(struct gfs2_sbd *sdp)
(unsigned long long)dirblk);
/* Can't use fsck_blockmap_set here because we don't
have an inode in memory. */
- gfs2_blockmap_set(bl, dirblk, gfs2_inode_invalid);
- check_n_fix_bitmap(sdp, dirblk, 0, gfs2_inode_invalid);
+ gfs2_blockmap_set(bl, dirblk, GFS2_BLKST_FREE);
+ check_n_fix_bitmap(sdp, dirblk, 0, GFS2_BLKST_FREE);
}
ip = fsck_load_inode(sdp, dirblk);
if (!ds.dotdir) {
diff --git a/gfs2/fsck/pass3.c b/gfs2/fsck/pass3.c
index 3e183e5..054953f 100644
--- a/gfs2/fsck/pass3.c
+++ b/gfs2/fsck/pass3.c
@@ -67,6 +67,7 @@ static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sdp,
struct dir_info *pdi;
uint8_t q_dotdot, q_treewalk;
int error = 0;
+ struct dir_info *dt_dotdot, *dt_treewalk;
di->checked = 1;
@@ -75,7 +76,7 @@ static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sdp,
if (di->dotdot_parent.no_addr == di->treewalk_parent) {
q_dotdot = block_type(di->dotdot_parent.no_addr);
- if (q_dotdot != gfs2_inode_dir) {
+ if (q_dotdot != GFS2_BLKST_DINODE) {
log_err( _("Orphaned directory at block %llu (0x%llx) "
"moved to lost+found\n"),
(unsigned long long)di->dinode.no_addr,
@@ -95,7 +96,9 @@ static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sdp,
(unsigned long long)di->treewalk_parent,
(unsigned long long)di->treewalk_parent);
q_dotdot = block_type(di->dotdot_parent.no_addr);
+ dt_dotdot = dirtree_find(di->dotdot_parent.no_addr);
q_treewalk = block_type(di->treewalk_parent);
+ dt_treewalk = dirtree_find(di->treewalk_parent);
/* if the dotdot entry isn't a directory, but the
* treewalk is, treewalk is correct - if the treewalk
* entry isn't a directory, but the dotdot is, dotdot
@@ -103,8 +106,8 @@ static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sdp,
* choose? if neither are directories, we have a
* problem - need to move this directory into lost+found
*/
- if (q_dotdot != gfs2_inode_dir) {
- if (q_treewalk != gfs2_inode_dir) {
+ if (q_dotdot != GFS2_BLKST_DINODE || dt_dotdot == NULL) {
+ if (q_treewalk != GFS2_BLKST_DINODE) {
log_err( _("Orphaned directory, move to "
"lost+found\n"));
return NULL;
@@ -120,7 +123,7 @@ static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sdp,
}
goto out;
}
- if (q_treewalk == gfs2_inode_dir) {
+ if (dt_treewalk) {
log_err( _("Both .. and treewalk parents are directories, "
"going with treewalk...\n"));
attach_dotdot_to(sdp, di->treewalk_parent,
@@ -247,7 +250,7 @@ int pass3(struct gfs2_sbd *sdp)
continue;
}
q = block_type(di->dinode.no_addr);
- if (q == gfs2_bad_block) {
+ if (q == GFS2_BLKST_UNLINKED) {
log_err( _("Found unlinked directory "
"containing bad block at block %llu"
" (0x%llx)\n"),
@@ -264,16 +267,14 @@ int pass3(struct gfs2_sbd *sdp)
/* Can't use fsck_blockmap_set
because we don't have ip */
gfs2_blockmap_set(bl, di->dinode.no_addr,
- gfs2_block_free);
+ GFS2_BLKST_FREE);
check_n_fix_bitmap(sdp, di->dinode.no_addr,
- 0, gfs2_block_free);
+ 0, GFS2_BLKST_FREE);
break;
} else
log_err( _("Unlinked directory with bad block remains\n"));
}
- if (q != gfs2_inode_dir && q != gfs2_inode_file &&
- q != gfs2_inode_lnk && q != gfs2_inode_device &&
- q != gfs2_inode_fifo && q != gfs2_inode_sock) {
+ if (q != GFS2_BLKST_DINODE) {
log_err( _("Unlinked block marked as an inode "
"is not an inode\n"));
if (!query(_("Clear the unlinked block?"
@@ -289,9 +290,9 @@ int pass3(struct gfs2_sbd *sdp)
/* Can't use fsck_blockmap_set
because we don't have ip */
gfs2_blockmap_set(bl, di->dinode.no_addr,
- gfs2_block_free);
+ GFS2_BLKST_FREE);
check_n_fix_bitmap(sdp, di->dinode.no_addr, 0,
- gfs2_block_free);
+ GFS2_BLKST_FREE);
log_err( _("The block was cleared\n"));
break;
}
@@ -310,7 +311,7 @@ int pass3(struct gfs2_sbd *sdp)
fsck_blockmap_set(ip,
di->dinode.no_addr,
_("zero-sized unlinked inode"),
- gfs2_block_free);
+ GFS2_BLKST_FREE);
fsck_inode_put(&ip);
break;
} else {
diff --git a/gfs2/fsck/pass4.c b/gfs2/fsck/pass4.c
index 324ea9f..f307782 100644
--- a/gfs2/fsck/pass4.c
+++ b/gfs2/fsck/pass4.c
@@ -71,7 +71,7 @@ static int scan_inode_list(struct gfs2_sbd *sdp) {
(unsigned long long)ii->di_num.no_addr,
(unsigned long long)ii->di_num.no_addr);
q = block_type(ii->di_num.no_addr);
- if (q == gfs2_bad_block) {
+ if (q == GFS2_BLKST_UNLINKED) {
log_err( _("Unlinked inode %llu (0x%llx) contains "
"bad blocks\n"),
(unsigned long long)ii->di_num.no_addr,
@@ -84,18 +84,13 @@ static int scan_inode_list(struct gfs2_sbd *sdp) {
check_metatree(ip, &pass4_fxns_delete);
fsck_blockmap_set(ip, ii->di_num.no_addr,
_("bad unlinked"),
- gfs2_block_free);
+ GFS2_BLKST_FREE);
fsck_inode_put(&ip);
continue;
} else
log_err( _("Unlinked inode with bad blocks not cleared\n"));
}
- if (q != gfs2_inode_dir &&
- q != gfs2_inode_file &&
- q != gfs2_inode_lnk &&
- q != gfs2_inode_device &&
- q != gfs2_inode_fifo &&
- q != gfs2_inode_sock) {
+ if (q != GFS2_BLKST_DINODE) {
log_err( _("Unlinked block %lld (0x%llx) "
"marked as inode is "
"not an inode (%d)\n"),
@@ -108,7 +103,7 @@ static int scan_inode_list(struct gfs2_sbd *sdp) {
check_metatree(ip, &pass4_fxns_delete);
fsck_blockmap_set(ip, ii->di_num.no_addr,
_("invalid unlinked"),
- gfs2_block_free);
+ GFS2_BLKST_FREE);
fsck_inode_put(&ip);
log_err( _("The inode was deleted\n"));
} else {
@@ -129,7 +124,7 @@ static int scan_inode_list(struct gfs2_sbd *sdp) {
"(y/n) "))) {
fsck_blockmap_set(ip, ii->di_num.no_addr,
_("unlinked zero-length"),
- gfs2_block_free);
+ GFS2_BLKST_FREE);
fsck_inode_put(&ip);
continue;
}
diff --git a/gfs2/fsck/pass5.c b/gfs2/fsck/pass5.c
index 2b8536d..fab3e5c 100644
--- a/gfs2/fsck/pass5.c
+++ b/gfs2/fsck/pass5.c
@@ -34,7 +34,7 @@ static int check_block_status(struct gfs2_sbd *sdp, char *buffer,
if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
return 0;
- q = blockmap_to_bitmap(block_type(block), sdp->gfs1);
+ q = block_type(block);
/* GFS1 file systems will have to suffer from slower fsck run
* times because in GFS, there's no 1:1 relationship between
* bits and counts. If a bit is marked "dinode" in GFS1, it
diff --git a/gfs2/fsck/util.c b/gfs2/fsck/util.c
index a0f6009..efdd132 100644
--- a/gfs2/fsck/util.c
+++ b/gfs2/fsck/util.c
@@ -375,7 +375,7 @@ int add_duplicate_ref(struct gfs2_inode *ip, uint64_t block,
q = block_type(ip->i_di.di_num.no_addr);
/* If it's an invalid dinode, put it first on the invalid
inode reference list otherwise put it on the normal list. */
- if (!inode_valid || q == gfs2_inode_invalid)
+ if (!inode_valid || q == GFS2_BLKST_UNLINKED)
osi_list_add_prev(&id->list, &dt->ref_invinode_list);
else {
/* If this is a system dinode, we want the duplicate
@@ -526,7 +526,7 @@ static int gfs2_blockmap_create(struct gfs2_bmap *bmap, uint64_t size)
/* Have to add 1 to BLOCKMAP_SIZE since it's 0-based and mallocs
* must be 1-based */
- bmap->mapsize = BLOCKMAP_SIZE4(size) + 1;
+ bmap->mapsize = BLOCKMAP_SIZE2(size) + 1;
if (!(bmap->map = calloc(bmap->mapsize, sizeof(char))))
return -ENOMEM;
@@ -560,8 +560,7 @@ struct gfs2_bmap *gfs2_bmap_create(struct gfs2_sbd *sdp, uint64_t size,
return il;
}
-int gfs2_blockmap_set(struct gfs2_bmap *bmap, uint64_t bblock,
- enum gfs2_mark_block mark)
+int gfs2_blockmap_set(struct gfs2_bmap *bmap, uint64_t bblock, int mark)
{
static unsigned char *byte;
static uint64_t b;
@@ -571,10 +570,10 @@ int gfs2_blockmap_set(struct gfs2_bmap *bmap, uint64_t bblock,
if (bblock > bmap->size)
return -1;
- byte = bmap->map + BLOCKMAP_SIZE4(bblock);
- b = BLOCKMAP_BYTE_OFFSET4(bblock);
- *byte &= ~(BLOCKMAP_MASK4 << b);
- *byte |= (mark & BLOCKMAP_MASK4) << b;
+ byte = bmap->map + BLOCKMAP_SIZE2(bblock);
+ b = BLOCKMAP_BYTE_OFFSET2(bblock);
+ *byte &= ~(BLOCKMAP_MASK2 << b);
+ *byte |= (mark & BLOCKMAP_MASK2) << b;
return 0;
}
@@ -598,61 +597,45 @@ void *gfs2_bmap_destroy(struct gfs2_sbd *sdp, struct gfs2_bmap *il)
int set_ip_blockmap(struct gfs2_inode *ip, int instree)
{
uint64_t block = ip->i_bh->b_blocknr;
- struct gfs2_sbd *sdp = ip->i_sbd;
uint32_t mode;
+ const char *ty;
- if (sdp->gfs1)
+ if (ip->i_sbd->gfs1)
mode = gfs_to_gfs2_mode(ip);
else
mode = ip->i_di.di_mode & S_IFMT;
switch (mode) {
case S_IFDIR:
- if (fsck_blockmap_set(ip, block, _("directory"),
- gfs2_inode_dir))
- goto bad_dinode;
- if (instree && !dirtree_insert(ip->i_di.di_num))
- goto bad_dinode;
+ ty = _("directory");
break;
case S_IFREG:
- if (fsck_blockmap_set(ip, block, _("file"), gfs2_inode_file))
- goto bad_dinode;
+ ty = _("file");
break;
case S_IFLNK:
- if (fsck_blockmap_set(ip, block, _("symlink"),
- gfs2_inode_lnk))
- goto bad_dinode;
+ ty = _("symlink");
break;
case S_IFBLK:
- if (fsck_blockmap_set(ip, block, _("block device"),
- gfs2_inode_device))
- goto bad_dinode;
+ ty = _("block device");
break;
case S_IFCHR:
- if (fsck_blockmap_set(ip, block, _("character device"),
- gfs2_inode_device))
- goto bad_dinode;
+ ty = _("character device");
break;
case S_IFIFO:
- if (fsck_blockmap_set(ip, block, _("fifo"),
- gfs2_inode_fifo))
- goto bad_dinode;
+ ty = _("fifo");
break;
case S_IFSOCK:
- if (fsck_blockmap_set(ip, block, _("socket"),
- gfs2_inode_sock))
- goto bad_dinode;
+ ty = _("socket");
break;
default:
- fsck_blockmap_set(ip, block, _("invalid mode"),
- gfs2_inode_invalid);
return -EINVAL;
}
+ if (fsck_blockmap_set(ip, block, ty, GFS2_BLKST_DINODE) ||
+ (mode == S_IFDIR && instree && !dirtree_insert(ip->i_di.di_num))) {
+ stack;
+ return -EPERM;
+ }
return 0;
-
-bad_dinode:
- stack;
- return -EPERM;
}
uint64_t find_free_blk(struct gfs2_sbd *sdp)
diff --git a/gfs2/fsck/util.h b/gfs2/fsck/util.h
index 66b9c7a..62f8ca6 100644
--- a/gfs2/fsck/util.h
+++ b/gfs2/fsck/util.h
@@ -28,9 +28,9 @@ extern void dup_listent_delete(struct duptree *dt, struct inode_with_dups *id);
extern const char *reftypes[ref_types + 1];
-#define BLOCKMAP_SIZE4(size) ((size) >> 1)
-#define BLOCKMAP_BYTE_OFFSET4(x) (((x) & 0x0000000000000001) << 2)
-#define BLOCKMAP_MASK4 (0xf)
+#define BLOCKMAP_SIZE2(size) ((size) >> 2)
+#define BLOCKMAP_BYTE_OFFSET2(x) ((x & 0x0000000000000003) << 1)
+#define BLOCKMAP_MASK2 (0x3)
static inline void astate_save(struct gfs2_inode *ip, struct alloc_state *as)
{
@@ -53,110 +53,18 @@ static inline uint8_t block_type(uint64_t bblock)
static uint64_t b;
static uint8_t btype;
- byte = bl->map + BLOCKMAP_SIZE4(bblock);
- b = BLOCKMAP_BYTE_OFFSET4(bblock);
- btype = (*byte & (BLOCKMAP_MASK4 << b )) >> b;
+ byte = bl->map + BLOCKMAP_SIZE2(bblock);
+ b = BLOCKMAP_BYTE_OFFSET2(bblock);
+ btype = (*byte & (BLOCKMAP_MASK2 << b )) >> b;
return btype;
}
-/* blockmap declarations and functions */
-enum gfs2_mark_block {
- gfs2_block_free = (0x0),
- gfs2_block_used = (0x1),
- gfs2_indir_blk = (0x2),
- /* These are inode block types (only): */
- gfs2_inode_dir = (0x3),
- gfs2_inode_file = (0x4),
-
- gfs2_inode_lnk = (0x5),
- gfs2_inode_device = (0x6), /* char or block device */
- gfs2_inode_fifo = (0x7),
- gfs2_inode_sock = (0x8),
- gfs2_inode_invalid = (0x9),
-
- /* misc block types: */
- gfs2_jdata = (0xa), /* gfs journaled data blocks */
- gfs2_meta_inval = (0xb),
- gfs2_leaf_blk = (0xc),
- gfs2_freemeta = (0xd), /* was: gfs2_meta_rgrp */
- gfs2_meta_eattr = (0xe),
-
- gfs2_bad_block = (0xf), /* Contains at least one bad block */
-};
-
static const inline char *block_type_string(uint8_t q)
{
- const char *blktyp[] = {
- "free",
- "data",
- "indirect meta",
- "directory",
- "file",
-
- "symlink",
- "device",
- "fifo",
- "socket",
- "invalid inode",
-
- "journaled data",
- "invalid meta",
- "dir leaf",
- "free metadata",
- "eattribute",
-
- "bad"};
- if (q < 16)
+ const char *blktyp[] = {"free", "data", "other", "inode", "invalid"};
+ if (q <= GFS2_BLKST_DINODE)
return (blktyp[q]);
- return blktyp[15];
-}
-
-/* Must be kept in sync with gfs2_mark_block enum above. Blocks marked as
- invalid or bad are considered metadata until actually freed. */
-static inline int blockmap_to_bitmap(enum gfs2_mark_block m, int gfs1)
-{
- static int bitmap_states[2][16] = {
- /* ---------------------- gfs2 ------------------------------*/
- {GFS2_BLKST_FREE, /* free */
- GFS2_BLKST_USED, /* data */
- GFS2_BLKST_USED, /* indirect data or rgrp meta */
- GFS2_BLKST_DINODE, /* directory */
- GFS2_BLKST_DINODE, /* file */
-
- GFS2_BLKST_DINODE, /* symlink */
- GFS2_BLKST_DINODE, /* block or char device */
- GFS2_BLKST_DINODE, /* fifo */
- GFS2_BLKST_DINODE, /* socket */
- GFS2_BLKST_FREE, /* invalid inode */
-
- GFS2_BLKST_USED, /* journaled data */
- GFS2_BLKST_FREE, /* invalid meta */
- GFS2_BLKST_USED, /* dir leaf */
- GFS2_BLKST_UNLINKED, /* GFS unlinked metadata */
- GFS2_BLKST_USED, /* eattribute */
-
- GFS2_BLKST_DINODE}, /* bad */
- /* ---------------------- gfs1 ----------------------------- */
- {GFS2_BLKST_FREE, /* free */
- GFS2_BLKST_USED, /* data */
- GFS2_BLKST_DINODE, /* indirect data or rgrp meta*/
- GFS2_BLKST_DINODE, /* directory */
- GFS2_BLKST_DINODE, /* file */
-
- GFS2_BLKST_DINODE, /* symlink */
- GFS2_BLKST_DINODE, /* block or char device */
- GFS2_BLKST_DINODE, /* fifo */
- GFS2_BLKST_DINODE, /* socket */
- GFS2_BLKST_FREE, /* invalid inode */
-
- GFS2_BLKST_DINODE, /* journaled data */
- GFS2_BLKST_FREE, /* invalid meta */
- GFS2_BLKST_DINODE, /* dir leaf */
- GFS2_BLKST_UNLINKED, /* GFS unlinked metadata */
- GFS2_BLKST_DINODE, /* eattribute */
-
- GFS2_BLKST_DINODE}}; /* bad */
- return bitmap_states[gfs1][m];
+ return blktyp[4];
}
static inline int is_dir(struct gfs2_dinode *dinode, int gfs1)
@@ -202,8 +110,7 @@ extern enum dup_ref_type get_ref_type(struct inode_with_dups *id);
extern struct gfs2_bmap *gfs2_bmap_create(struct gfs2_sbd *sdp, uint64_t size,
uint64_t *addl_mem_needed);
extern void *gfs2_bmap_destroy(struct gfs2_sbd *sdp, struct gfs2_bmap *il);
-extern int gfs2_blockmap_set(struct gfs2_bmap *il, uint64_t block,
- enum gfs2_mark_block mark);
+extern int gfs2_blockmap_set(struct gfs2_bmap *il, uint64_t block, int mark);
extern int set_ip_blockmap(struct gfs2_inode *ip, int instree);
extern char generic_interrupt(const char *caller, const char *where,
const char *progress, const char *question,
9 years
gfs2-utils: RHEL7 - mkfs.gfs2: Remove unused declarations
by Andrew Price
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=6abfaa91...
Commit: 6abfaa91f56f771c2ebaa6bc77d76503ac9bd899
Parent: 0263d05cff300f77300caa0e3f9a89740e129c97
Author: Andrew Price <anprice(a)redhat.com>
AuthorDate: Wed Feb 4 12:17:32 2015 +0000
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Wed Apr 1 16:51:35 2015 +0100
mkfs.gfs2: Remove unused declarations
Remove now-unused declarations of main_{grow,jadd,mkfs} and a never-used
declaration of main_shrink.
Signed-off-by: Andrew Price <anprice(a)redhat.com>
---
gfs2/mkfs/gfs2_mkfs.h | 12 ------------
1 files changed, 0 insertions(+), 12 deletions(-)
diff --git a/gfs2/mkfs/gfs2_mkfs.h b/gfs2/mkfs/gfs2_mkfs.h
index 377c14b..75f70e6 100644
--- a/gfs2/mkfs/gfs2_mkfs.h
+++ b/gfs2/mkfs/gfs2_mkfs.h
@@ -6,18 +6,6 @@
#include "osi_list.h"
#include "copyright.cf"
-/* main_grow */
-extern void main_grow(int argc, char *argv[]);
-
-/* main_jadd */
-extern void main_jadd(int argc, char *argv[]);
-
-/* main_mkfs */
-extern void main_mkfs(int argc, char *argv[]);
-
-/* main_shrink */
-extern void main_shrink(int argc, char *argv[]);
-
/* die() used to be in libgfs2.h */
static __inline__ __attribute__((noreturn, format (printf, 1, 2)))
void die(const char *fmt, ...)
9 years
gfs2-utils: RHEL7 - gfs2-utils build: Add a configure script summary
by Andrew Price
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=0263d05c...
Commit: 0263d05cff300f77300caa0e3f9a89740e129c97
Parent: 30d1c654b637f38f168e13a489a3c9f110fca63e
Author: Andrew Price <anprice(a)redhat.com>
AuthorDate: Tue Jan 27 14:12:17 2015 +0000
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Wed Apr 1 16:51:35 2015 +0100
gfs2-utils build: Add a configure script summary
Print a nicely formatted summary of some of the more interesting
configure options. Required some tweaking of earlier configure stages
for accuracy.
Signed-off-by: Andrew Price <anprice(a)redhat.com>
---
configure.ac | 31 +++++++++++++++++++------------
1 files changed, 19 insertions(+), 12 deletions(-)
diff --git a/configure.ac b/configure.ac
index a523be3..a41eb57 100644
--- a/configure.ac
+++ b/configure.ac
@@ -88,10 +88,10 @@ check_lib_no_libs() {
# local options
AC_ARG_ENABLE([debug],
AC_HELP_STRING([--enable-debug],[enable debug build [default=no]]),
- [default="no"])
+ [], [enable_debug="no"])
AC_ARG_ENABLE([gcov],
AC_HELP_STRING([--enable-gcov],[enable coverage instrumentation [default=no]]),
- [default="no"])
+ [], [enable_gcov="no"])
# We use the Check framework for unit tests
PKG_CHECK_MODULES([check], [check >= 0.9.8],
@@ -175,6 +175,9 @@ if test "x${enable_gcov}" = xyes; then
if ! cc_supports_flag $GCOV_CFLAGS; then
AC_MSG_ERROR([your compiler does not support coverage instrumentation])
fi
+ if test "x${enable_debug}" = xyes; then
+ enable_debug="no (gcov enabled)"
+ fi
OPT_CFLAGS="-O0 $GCOV_CFLAGS"
fi
@@ -206,10 +209,8 @@ for j in $WARNLIST; do
fi
done
-CFLAGS="$ENV_CFLAGS $OPT_CFLAGS $GDB_FLAGS \
- $EXTRA_WARNINGS $WERROR_CFLAGS"
-CPPFLAGS="-I\$(top_builddir)/make -I\$(top_srcdir)/make \
- -I. $ENV_CPPFLAGS"
+CFLAGS="$ENV_CFLAGS $OPT_CFLAGS $GDB_FLAGS $EXTRA_WARNINGS $WERROR_CFLAGS"
+CPPFLAGS="-I\$(top_builddir)/make -I\$(top_srcdir)/make -I. $ENV_CPPFLAGS"
LDFLAGS="$ENV_LDFLAGS"
AC_CONFIG_TESTDIR([tests], [gfs2/libgfs2:gfs2/mkfs:gfs2/fsck:gfs2/edit:gfs2/convert:gfs2/tune:tests])
@@ -232,9 +233,15 @@ AC_CONFIG_FILES([Makefile
AC_OUTPUT
-if test x"${have_check}" != "xyes"; then
- AC_MSG_NOTICE([package 'check' not found; unit tests will not be built])
-fi
-if test x"${enable_gcov}" = "xyes"; then
- AC_MSG_NOTICE([code coverage enabled; optimization will be disabled])
-fi
+echo
+echo " Configure summary"
+echo " ==================="
+echo " prefix : $prefix"
+echo " exec_prefix : $exec_prefix"
+echo " sbindir : $sbindir"
+echo " ------------------"
+echo " debug build : $enable_debug"
+echo " C unit tests : $have_check"
+echo " gcov build : $enable_gcov"
+echo
+echo "Now run 'make' to build and 'make check' to run tests"
9 years
gfs2-utils: RHEL7 - fsck.gfs2: Simplify bad_journalname
by Andrew Price
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=30d1c654...
Commit: 30d1c654b637f38f168e13a489a3c9f110fca63e
Parent: 1be8d75fd107390cb422dabf25062f9f7423c25c
Author: Andrew Price <anprice(a)redhat.com>
AuthorDate: Tue Jan 27 12:05:07 2015 +0000
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Wed Apr 1 16:51:35 2015 +0100
fsck.gfs2: Simplify bad_journalname
Remove the need for a temporary string and strncpy call by passing the
length of the string to printf.
Signed-off-by: Andrew Price <anprice(a)redhat.com>
---
gfs2/fsck/initialize.c | 8 ++------
1 files changed, 2 insertions(+), 6 deletions(-)
diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c
index 1ab078b..c052205 100644
--- a/gfs2/fsck/initialize.c
+++ b/gfs2/fsck/initialize.c
@@ -1513,14 +1513,10 @@ static int init_rindex(struct gfs2_sbd *sdp)
static void bad_journalname(const char *filename, int len)
{
- char tmp_name[64];
-
if (len >= 64)
len = 63;
- strncpy(tmp_name, filename, len);
- tmp_name[len] = '\0';
- log_debug(_("Journal index entry '%s' has an invalid filename.\n"),
- tmp_name);
+ log_debug(_("Journal index entry '%.*s' has an invalid filename.\n"),
+ len, filename);
}
/**
9 years
gfs2-utils: RHEL7 - fsck.gfs2: Fix 'initializer element is not constant' build error
by Andrew Price
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=1be8d75f...
Commit: 1be8d75fd107390cb422dabf25062f9f7423c25c
Parent: 18894bea111515a8c2f8776df21b7c4396d63ae1
Author: Andrew Price <anprice(a)redhat.com>
AuthorDate: Tue Jan 27 11:39:35 2015 +0000
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Wed Apr 1 16:51:35 2015 +0100
fsck.gfs2: Fix 'initializer element is not constant' build error
This error occurs when gfs2-utils is compiled with -std options more
recent than gnu89:
CC fsck_gfs2-main.o
main.c:39:38: error: initializer element is not constant
struct osi_root dup_blocks = (struct osi_root) { NULL, };
^
main.c:40:35: error: initializer element is not constant
struct osi_root dirtree = (struct osi_root) { NULL, };
^
main.c:41:37: error: initializer element is not constant
struct osi_root inodetree = (struct osi_root) { NULL, };
^
As far as I can tell, with C89/gnu89 the use of a cast in this context
is undefined behaviour and the later standards are more strict about it,
hence the error. As the standards specify that members of objects with
static storage duration are zeroed/NULLed anyway, the initializers can
be removed to achieve the intended result.
Signed-off-by: Andrew Price <anprice(a)redhat.com>
---
gfs2/fsck/main.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/gfs2/fsck/main.c b/gfs2/fsck/main.c
index a4af25d..658cd17 100644
--- a/gfs2/fsck/main.c
+++ b/gfs2/fsck/main.c
@@ -36,9 +36,9 @@ const char *pass = "";
uint64_t last_data_block;
uint64_t first_data_block;
int preen = 0, force_check = 0;
-struct osi_root dup_blocks = (struct osi_root) { NULL, };
-struct osi_root dirtree = (struct osi_root) { NULL, };
-struct osi_root inodetree = (struct osi_root) { NULL, };
+struct osi_root dup_blocks;
+struct osi_root dirtree;
+struct osi_root inodetree;
int dups_found = 0, dups_found_first = 0;
struct gfs_sb *sbd1 = NULL;
int sb_fixed = 0;
9 years
gfs2-utils: RHEL7 - fsck.gfs2: rgrp block count reform
by Andrew Price
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=18894bea...
Commit: 18894bea111515a8c2f8776df21b7c4396d63ae1
Parent: e1d04e00fed15e6e237ee4f6eb122f92a8c3cfe4
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Tue Jan 13 13:18:01 2015 -0600
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Wed Apr 1 16:51:35 2015 +0100
fsck.gfs2: rgrp block count reform
In the past, pass5 has kept track of different counts for the different
metadata types, but the counts did not correspond to the type in the
bitmap. This patch changes pass5 so that it makes a little more sense.
There should be a straightforward blockmap-to-bitmap conversion, and
the counts should be based on the bitmap type. For example, before the
patch, the rgrp's inode count would be kept in count[1], but in the
bitmap, dinodes are of type 3. So this patch reworks that system so
that the count of dinodes is kept in count[3] and so forth, and it
uses a simple blockmap-to-bitmap to figure out the index to "count".
This breaks down for GFS1 which keeps a few extra numbers in the rgrp,
however this patch compensates for that. This patch is being done
as a precursor to another patch that reduces fsck's memory requirements
by using a blockmap that's 1:1 with the bitmaps rather than today's
blockmap that's 4:1.
---
gfs2/fsck/pass5.c | 167 ++++++++++++++---------------------------------------
1 files changed, 44 insertions(+), 123 deletions(-)
diff --git a/gfs2/fsck/pass5.c b/gfs2/fsck/pass5.c
index b2e8adf..2b8536d 100644
--- a/gfs2/fsck/pass5.c
+++ b/gfs2/fsck/pass5.c
@@ -12,94 +12,6 @@
#include "fsck.h"
#include "util.h"
-static int gfs1_convert_mark(uint8_t q, uint32_t *count)
-{
- switch(q) {
-
- case gfs2_meta_inval:
- case gfs2_inode_invalid:
- /* Convert invalid metadata to free blocks */
- case gfs2_block_free:
- count[0]++;
- return GFS2_BLKST_FREE;
-
- case gfs2_block_used:
- count[2]++;
- return GFS2_BLKST_USED;
-
- case gfs2_inode_dir:
- case gfs2_inode_file:
- case gfs2_inode_lnk:
- case gfs2_inode_device:
- case gfs2_inode_fifo:
- case gfs2_inode_sock:
- count[1]++;
- return GFS2_BLKST_DINODE;
-
- case gfs2_indir_blk:
- case gfs2_leaf_blk:
- /*case gfs2_meta_rgrp:*/
- case gfs2_jdata: /* gfs1 jdata blocks count as "metadata" and gfs1
- metadata is marked the same as gfs2 inode in the
- bitmap. */
- case gfs2_meta_eattr:
- count[3]++;
- return GFS2_BLKST_DINODE;
-
- case gfs2_freemeta:
- count[4]++;
- return GFS2_BLKST_UNLINKED;
-
- default:
- log_err( _("Invalid block type %d found\n"), q);
- }
- return -1;
-}
-
-static int gfs2_convert_mark(uint8_t q, uint32_t *count)
-{
- switch(q) {
-
- case gfs2_meta_inval:
- case gfs2_inode_invalid:
- /* Convert invalid metadata to free blocks */
- case gfs2_block_free:
- count[0]++;
- return GFS2_BLKST_FREE;
-
- case gfs2_block_used:
- count[2]++;
- return GFS2_BLKST_USED;
-
- case gfs2_inode_dir:
- case gfs2_inode_file:
- case gfs2_inode_lnk:
- case gfs2_inode_device:
- case gfs2_jdata: /* gfs1 jdata blocks count as "metadata" and gfs1
- metadata is marked the same as gfs2 inode in the
- bitmap. */
- case gfs2_inode_fifo:
- case gfs2_inode_sock:
- count[1]++;
- return GFS2_BLKST_DINODE;
-
- case gfs2_indir_blk:
- case gfs2_leaf_blk:
- case gfs2_meta_eattr:
- count[2]++;
- return GFS2_BLKST_USED;
-
- case gfs2_freemeta:
- log_err( _("Invalid freemeta type %d found\n"), q);
- count[4]++;
- return -1;
-
- default:
- log_err( _("Invalid block type %d found\n"), q);
- }
- return -1;
-}
-
static int check_block_status(struct gfs2_sbd *sdp, char *buffer,
unsigned int buflen, uint64_t *rg_block,
uint64_t rg_data, uint32_t *count)
@@ -107,7 +19,6 @@ static int check_block_status(struct gfs2_sbd *sdp, char *buffer,
unsigned char *byte, *end;
unsigned int bit;
unsigned char rg_status;
- int block_status;
uint8_t q;
uint64_t block;
@@ -123,26 +34,33 @@ static int check_block_status(struct gfs2_sbd *sdp, char *buffer,
if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
return 0;
- q = block_type(block);
-
- if (sdp->gfs1)
- block_status = gfs1_convert_mark(q, count);
- else
- block_status = gfs2_convert_mark(q, count);
-
- if (block_status < 0) {
- log_err( _("Invalid status for block %llu (0x%llx).\n"),
- (unsigned long long)block,
- (unsigned long long)block);
- return block_status;
+ q = blockmap_to_bitmap(block_type(block), sdp->gfs1);
+ /* GFS1 file systems will have to suffer from slower fsck run
+ * times because in GFS, there's no 1:1 relationship between
+ * bits and counts. If a bit is marked "dinode" in GFS1, it
+ * may be dinode -OR- any kind of metadata. I consider GFS1 to
+ * be a rare exception, so acceptable loss at this point. So
+ * we must determine whether it's really a dinode or other
+ * metadata by reading it in. */
+ if (sdp->gfs1 && q == GFS2_BLKST_DINODE) {
+ struct gfs2_buffer_head *bh;
+
+ bh = bread(sdp, block);
+ if (gfs2_check_meta(bh, GFS2_METATYPE_DI) == 0)
+ count[GFS2_BLKST_DINODE]++;
+ else
+ count[GFS2_BLKST_USED]++;
+ brelse(bh);
+ } else {
+ count[q]++;
}
+
/* If one node opens a file and another node deletes it, we
may be left with a block that appears to be "unlinked" in
the bitmap, but nothing links to it. This is a valid case
and should be cleaned up by the file system eventually.
So we ignore it. */
- if (rg_status == GFS2_BLKST_UNLINKED &&
- block_status == GFS2_BLKST_FREE) {
+ if (q == GFS2_BLKST_UNLINKED) {
log_err( _("Unlinked inode found at block %llu "
"(0x%llx).\n"),
(unsigned long long)block,
@@ -150,33 +68,33 @@ static int check_block_status(struct gfs2_sbd *sdp, char *buffer,
if (query(_("Do you want to reclaim the block? "
"(y/n) "))) {
lgfs2_rgrp_t rg = gfs2_blk2rgrpd(sdp, block);
- if (gfs2_set_bitmap(rg, block, block_status))
+ if (gfs2_set_bitmap(rg, block, GFS2_BLKST_FREE))
log_err(_("Unlinked block %llu "
"(0x%llx) bitmap not fixed."
"\n"),
(unsigned long long)block,
(unsigned long long)block);
- else
+ else {
log_err(_("Unlinked block %llu "
"(0x%llx) bitmap fixed.\n"),
(unsigned long long)block,
(unsigned long long)block);
+ count[GFS2_BLKST_UNLINKED]--;
+ count[GFS2_BLKST_FREE]++;
+ }
} else {
log_info( _("Unlinked block found at block %llu"
" (0x%llx), left unchanged.\n"),
(unsigned long long)block,
(unsigned long long)block);
}
- } else if (rg_status != block_status) {
- const char *blockstatus[] = {"Free", "Data",
- "Unlinked", "inode"};
-
+ } else if (rg_status != q) {
log_err( _("Block %llu (0x%llx) bitmap says %u (%s) "
"but FSCK saw %u (%s)\n"),
(unsigned long long)block,
(unsigned long long)block, rg_status,
- blockstatus[rg_status], block_status,
- blockstatus[block_status]);
+ block_type_string(rg_status), q,
+ block_type_string(q));
if (q) /* Don't print redundant "free" */
log_err( _("Metadata type is %u (%s)\n"), q,
block_type_string(q));
@@ -185,7 +103,7 @@ static int check_block_status(struct gfs2_sbd *sdp, char *buffer,
(unsigned long long)block,
(unsigned long long)block)) {
lgfs2_rgrp_t rg = gfs2_blk2rgrpd(sdp, block);
- if (gfs2_set_bitmap(rg, block, block_status))
+ if (gfs2_set_bitmap(rg, block, q))
log_err( _("Repair failed.\n"));
else
log_err( _("Fixed.\n"));
@@ -235,38 +153,41 @@ static void update_rgrp(struct gfs2_sbd *sdp, struct rgrp_tree *rgp,
rgp->rg.rg_free = count[0];
update = 1;
}
- if (rgp->rg.rg_dinodes != count[1]) {
+ if (rgp->rg.rg_dinodes != count[3]) {
log_err( _("RG #%llu (0x%llx) Inode count inconsistent: is "
"%u should be %u\n"),
(unsigned long long)rgp->ri.ri_addr,
(unsigned long long)rgp->ri.ri_addr,
- rgp->rg.rg_dinodes, count[1]);
- rgp->rg.rg_dinodes = count[1];
+ rgp->rg.rg_dinodes, count[3]);
+ rgp->rg.rg_dinodes = count[3];
update = 1;
}
- if (sdp->gfs1 && gfs1rg->rg_usedmeta != count[3]) {
+ if (sdp->gfs1 && gfs1rg->rg_usedmeta != count[1]) {
log_err( _("RG #%llu (0x%llx) Used metadata count "
"inconsistent: is %u should be %u\n"),
(unsigned long long)rgp->ri.ri_addr,
(unsigned long long)rgp->ri.ri_addr,
- gfs1rg->rg_usedmeta, count[3]);
- gfs1rg->rg_usedmeta = count[3];
+ gfs1rg->rg_usedmeta, count[1]);
+ gfs1rg->rg_usedmeta = count[1];
update = 1;
}
- if (sdp->gfs1 && gfs1rg->rg_freemeta != count[4]) {
+ if (sdp->gfs1 && gfs1rg->rg_freemeta != count[2]) {
log_err( _("RG #%llu (0x%llx) Free metadata count "
"inconsistent: is %u should be %u\n"),
(unsigned long long)rgp->ri.ri_addr,
(unsigned long long)rgp->ri.ri_addr,
- gfs1rg->rg_freemeta, count[4]);
- gfs1rg->rg_freemeta = count[4];
+ gfs1rg->rg_freemeta, count[2]);
+ gfs1rg->rg_freemeta = count[2];
update = 1;
}
- if (!sdp->gfs1 && (rgp->ri.ri_data - count[0] - count[1]) != count[2]) {
+ if (!sdp->gfs1 && (rgp->ri.ri_data != count[0] + count[1] +
+ count[2] + count[3])) {
/* FIXME not sure how to handle this case ATM - it
* means that the total number of blocks we've counted
* exceeds the blocks in the rg */
- log_err( _("Internal fsck error - AAHHH!\n"));
+ log_err( _("Internal fsck error: %u != %u + %u + %u + %u\n"),
+ rgp->ri.ri_data, count[0], count[1], count[2],
+ count[3]);
exit(FSCK_ERROR);
}
if (update) {
9 years
gfs2-utils: RHEL7 - fsck.gfs2: Check the integrity of the journal index
by Andrew Price
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=e1d04e00...
Commit: e1d04e00fed15e6e237ee4f6eb122f92a8c3cfe4
Parent: 33aba2e2eac3c7b920230eff868d14a1d48c1f8f
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Mon Jan 12 15:10:08 2015 -0600
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Wed Apr 1 16:51:35 2015 +0100
fsck.gfs2: Check the integrity of the journal index
This patch checks the jindex system directory to make sure the entries
all start with "journal" and so forth. If not, the jindex is deleted
and rebuilt. As part of this patch, I moved where we read in the rindex
file and rgrps to an earlier point in time, before the journals are
replayed. This allows us to remove a dummied-up rgrp kludge in the code.
However, if the replayed journal block is part of an rgrp, we need to
refresh the rgrp based on the values rewritten from the journal.
---
gfs2/fsck/fs_recovery.c | 53 ++++++++------
gfs2/fsck/initialize.c | 171 ++++++++++++++++++++++++++++++++++++-----------
gfs2/fsck/metawalk.c | 17 +++--
gfs2/fsck/metawalk.h | 1 +
gfs2/fsck/pass1.c | 8 +-
5 files changed, 176 insertions(+), 74 deletions(-)
diff --git a/gfs2/fsck/fs_recovery.c b/gfs2/fsck/fs_recovery.c
index 095d118..abb8187 100644
--- a/gfs2/fsck/fs_recovery.c
+++ b/gfs2/fsck/fs_recovery.c
@@ -96,6 +96,30 @@ void gfs2_revoke_clean(struct gfs2_sbd *sdp)
}
}
+static void refresh_rgrp(struct gfs2_sbd *sdp, struct rgrp_tree *rgd,
+ struct gfs2_buffer_head *bh, uint64_t blkno)
+{
+ int i;
+
+ log_debug(_("Block is part of rgrp 0x%llx; refreshing the rgrp.\n"),
+ (unsigned long long)rgd->ri.ri_addr);
+ for (i = 0; i < rgd->ri.ri_length; i++) {
+ if (rgd->bits[i].bi_bh->b_blocknr != blkno)
+ continue;
+
+ memcpy(rgd->bits[i].bi_bh->b_data, bh->b_data, sdp->bsize);
+ bmodified(rgd->bits[i].bi_bh);
+ if (i == 0) { /* this is the rgrp itself */
+ if (sdp->gfs1)
+ gfs_rgrp_in((struct gfs_rgrp *)&rgd->rg,
+ rgd->bits[0].bi_bh);
+ else
+ gfs2_rgrp_in(&rgd->rg, rgd->bits[0].bi_bh);
+ }
+ break;
+ }
+}
+
static int buf_lo_scan_elements(struct gfs2_inode *ip, unsigned int start,
struct gfs2_log_descriptor *ld, __be64 *ptr,
int pass)
@@ -105,6 +129,7 @@ static int buf_lo_scan_elements(struct gfs2_inode *ip, unsigned int start,
struct gfs2_buffer_head *bh_log, *bh_ip;
uint64_t blkno;
int error = 0;
+ struct rgrp_tree *rgd;
if (pass != 1 || be32_to_cpu(ld->ld_type) != GFS2_LOG_DESC_METADATA)
return 0;
@@ -147,6 +172,9 @@ static int buf_lo_scan_elements(struct gfs2_inode *ip, unsigned int start,
error = -EIO;
} else {
bmodified(bh_ip);
+ rgd = gfs2_blk2rgrpd(sdp, blkno);
+ if (rgd && blkno < rgd->ri.ri_data0)
+ refresh_rgrp(sdp, rgd, bh_ip, blkno);
}
brelse(bh_log);
@@ -676,28 +704,8 @@ int replay_journals(struct gfs2_sbd *sdp, int preen, int force_check,
for(i = 0; i < sdp->md.journals; i++) {
if (sdp->md.journal[i]) {
- struct rgrp_tree rgd;
- struct gfs2_bitmap bits;
-
- /* The real rgrp tree hasn't been built at this point,
- * so we need to dummy one up that covers the whole
- * file system so basic functions in check_metatree
- * don't segfault. */
- rgd.start = sdp->sb_addr + 1;
- rgd.length = 1;
- bits.bi_bh = NULL;
- bits.bi_start = 0;
- bits.bi_len = sdp->fssize / GFS2_NBBY;
- rgd.bits = &bits;
- rgd.ri.ri_addr = sdp->sb_addr + 1;
- rgd.ri.ri_length = 1;
- rgd.ri.ri_data0 = sdp->sb_addr + 2;
- rgd.ri.ri_data = sdp->fssize - (sdp->sb_addr + 2);
-
- sdp->rgtree.osi_node = (struct osi_node *)&rgd;
error = check_metatree(sdp->md.journal[i],
&rangecheck_journal);
- sdp->rgtree.osi_node = NULL;
if (error)
/* Don't use fsck_inode_put here because it's a
system file and we need to dismantle it. */
@@ -707,8 +715,7 @@ int replay_journals(struct gfs2_sbd *sdp, int preen, int force_check,
if (!sdp->md.journal[i]) {
log_err(_("File system journal \"journal%d\" is "
"missing or corrupt: pass1 will try to "
- "recreate it.\n"),
- i);
+ "recreate it.\n"), i);
continue;
}
if (!error) {
@@ -755,7 +762,7 @@ int ji_update(struct gfs2_sbd *sdp)
struct gfs_jindex ji;
if (!ip) {
- log_crit("Journal index inode not found.\n");
+ log_crit(_("Journal index inode not found.\n"));
return -1;
}
diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c
index 4e52262..1ab078b 100644
--- a/gfs2/fsck/initialize.c
+++ b/gfs2/fsck/initialize.c
@@ -142,7 +142,7 @@ static int set_block_ranges(struct gfs2_sbd *sdp)
uint64_t rmin = 0;
int error;
- log_info( _("Setting block ranges...\n"));
+ log_info( _("Setting block ranges..."));
for (n = osi_first(&sdp->rgtree); n; n = next) {
next = osi_next(n);
@@ -184,9 +184,12 @@ static int set_block_ranges(struct gfs2_sbd *sdp)
goto fail;
}
+ log_info(_("0x%llx to 0x%llx\n"), (unsigned long long)first_data_block,
+ (unsigned long long)last_data_block);
return 0;
fail:
+ log_info( _("Error\n"));
return -1;
}
@@ -685,10 +688,6 @@ static int init_system_inodes(struct gfs2_sbd *sdp)
if (sdp->md.rooti == NULL)
return -1;
- err = fetch_rgrps(sdp);
- if (err)
- return err;
-
/*******************************************************************
***************** Initialize more system inodes *****************
*******************************************************************/
@@ -711,8 +710,8 @@ static int init_system_inodes(struct gfs2_sbd *sdp)
gfs2_lookupi(sdp->master_dir, "inum", 4,
&sdp->md.inum);
if (!sdp->md.inum) {
- log_crit("System inum inode was not rebuilt. "
- "Aborting.\n");
+ log_crit(_("System inum inode was not rebuilt."
+ " Aborting.\n"));
goto fail;
}
}
@@ -811,8 +810,8 @@ static int init_system_inodes(struct gfs2_sbd *sdp)
if (!sdp->gfs1 && !sdp->md.qinode) {
if (!query( _("The gfs2 system quota inode is missing. "
"Okay to rebuild it? (y/n) "))) {
- log_crit("System quota inode was not "
- "rebuilt. Aborting.\n");
+ log_crit(_("System quota inode was not "
+ "rebuilt. Aborting.\n"));
goto fail;
}
err = build_quota(sdp);
@@ -822,8 +821,8 @@ static int init_system_inodes(struct gfs2_sbd *sdp)
}
gfs2_lookupi(sdp->master_dir, "quota", 5, &sdp->md.qinode);
if (!sdp->md.qinode) {
- log_crit("Unable to rebuild system quota file "
- "inode. Aborting.\n");
+ log_crit(_("Unable to rebuild system quota file "
+ "inode. Aborting.\n"));
goto fail;
}
}
@@ -1357,7 +1356,7 @@ static int reconstruct_single_journal(struct gfs2_sbd *sdp, int jnum,
srandom(time(NULL));
sequence = ji_nsegment / (RAND_MAX + 1.0) * random();
- log_info("Clearing journal %d\n", jnum);
+ log_info(_("Clearing journal %d\n"), jnum);
for (seg = 0; seg < ji_nsegment; seg++){
memset(&lh, 0, sizeof(struct gfs_log_header));
@@ -1512,6 +1511,66 @@ static int init_rindex(struct gfs2_sbd *sdp)
return 0;
}
+static void bad_journalname(const char *filename, int len)
+{
+ char tmp_name[64];
+
+ if (len >= 64)
+ len = 63;
+ strncpy(tmp_name, filename, len);
+ tmp_name[len] = '\0';
+ log_debug(_("Journal index entry '%s' has an invalid filename.\n"),
+ tmp_name);
+}
+
+/**
+ * check_jindex_dent - check the jindex directory entries
+ *
+ * This function makes sure the directory entries of the jindex are valid.
+ * If they're not '.' or '..' they better have the form journalXXX.
+ */
+static int check_jindex_dent(struct gfs2_inode *ip, struct gfs2_dirent *dent,
+ struct gfs2_dirent *prev_de,
+ struct gfs2_buffer_head *bh, char *filename,
+ uint32_t *count, int *lindex, void *priv)
+{
+ struct gfs2_dirent dentry, *de;
+ int i;
+
+ memset(&dentry, 0, sizeof(struct gfs2_dirent));
+ gfs2_dirent_in(&dentry, (char *)dent);
+ de = &dentry;
+
+ if (de->de_name_len == 1 && filename[0] == '.')
+ goto dirent_good;
+ if (de->de_name_len == 2 && filename[0] == '.' && filename[1] == '.')
+ goto dirent_good;
+
+ if ((de->de_name_len >= 11) || /* "journal9999" */
+ (de->de_name_len <= 7) ||
+ (strncmp(filename, "journal", 7))) {
+ bad_journalname(filename, de->de_name_len);
+ return -1;
+ }
+ for (i = 7; i < de->de_name_len; i++) {
+ if (filename[i] < '0' || filename[i] > '9') {
+ bad_journalname(filename, de->de_name_len);
+ return -2;
+ }
+ }
+
+dirent_good:
+ /* Return the number of leaf entries so metawalk doesn't flag this
+ leaf as having none. */
+ *count = be16_to_cpu(((struct gfs2_leaf *)bh->b_data)->lf_entries);
+ return 0;
+}
+
+struct metawalk_fxns jindex_check_fxns = {
+ .private = NULL,
+ .check_dentry = check_jindex_dent,
+};
+
/**
* init_jindex - read in the rindex file
*/
@@ -1521,6 +1580,7 @@ static int init_jindex(struct gfs2_sbd *sdp)
****************** Fill in journal information ******************
*******************************************************************/
+ log_debug(_("Validating the journal index.\n"));
/* rgrepair requires the journals be read in in order to distinguish
"real" rgrps from rgrps that are just copies left in journals. */
if (sdp->gfs1)
@@ -1537,24 +1597,52 @@ static int init_jindex(struct gfs2_sbd *sdp)
"jindex file.\n"));
return -1;
}
- /* In order to rebuild jindex, we need some valid
- rgrps in memory. Temporarily read those in. */
- err = fetch_rgrps(sdp);
- if (err)
- return err;
err = build_jindex(sdp);
- /* Free rgrps read in earlier (re-read them later) */
- gfs2_rgrp_free(&sdp->rgtree);
if (err) {
log_crit(_("Error %d rebuilding jindex\n"), err);
return err;
}
+ gfs2_lookupi(sdp->master_dir, "jindex", 6, &sdp->md.jiinode);
+ }
+
+ /* check for irrelevant entries in jindex. Can't use check_dir because
+ that creates and destroys the inode, which we don't want. */
+ if (!sdp->gfs1) {
+ int error;
+
+ log_debug(_("Checking the integrity of the journal index.\n"));
+ if (sdp->md.jiinode->i_di.di_flags & GFS2_DIF_EXHASH)
+ error = check_leaf_blks(sdp->md.jiinode,
+ &jindex_check_fxns);
+ else
+ error = check_linear_dir(sdp->md.jiinode,
+ sdp->md.jiinode->i_bh,
+ &jindex_check_fxns);
+ if (error) {
+ log_err(_("The system journal index is damaged.\n"));
+ if (!query( _("Okay to rebuild it? (y/n) "))) {
+ log_crit(_("Error: cannot proceed without a "
+ "valid jindex file.\n"));
+ return -1;
+ }
+ inode_put(&sdp->md.jiinode);
+ gfs2_dirent_del(sdp->master_dir, "jindex", 6);
+ log_err(_("Corrupt journal index was removed.\n"));
+ error = build_jindex(sdp);
+ if (error) {
+ log_err(_("Error rebuilding journal "
+ "index: Cannot continue.\n"));
+ return error;
+ }
+ gfs2_lookupi(sdp->master_dir, "jindex", 6,
+ &sdp->md.jiinode);
+ }
}
/* read in the ji data */
if (ji_update(sdp)){
- log_err( _("Unable to read in jindex inode.\n"));
+ log_err( _("Unable to read jindex inode.\n"));
return -1;
}
return 0;
@@ -1655,31 +1743,34 @@ int initialize(struct gfs2_sbd *sdp, int force_check, int preen,
if (init_rindex(sdp))
return FSCK_ERROR;
- /* We need to read in jindex in order to replay the journals */
- if (init_jindex(sdp))
+ if (fetch_rgrps(sdp))
return FSCK_ERROR;
- /* If GFS, rebuild the journals. If GFS2, replay them. We don't have
- the smarts to replay GFS1 journals (neither did gfs_fsck). */
-
- if (sdp->gfs1) {
- if (reconstruct_journals(sdp))
+ /* We need to read in jindex in order to replay the journals. If
+ there's an error, we may proceed and let init_system_inodes
+ try to rebuild it. */
+ if (init_jindex(sdp) == 0) {
+ /* If GFS, rebuild the journals. If GFS2, replay them. We don't
+ have the smarts to replay GFS1 journals (neither did
+ gfs_fsck). */
+ if (sdp->gfs1) {
+ if (reconstruct_journals(sdp))
+ return FSCK_ERROR;
+ } else if (replay_journals(sdp, preen, force_check,
+ &clean_journals)) {
+ if (!opts.no && preen_is_safe(sdp, preen, force_check))
+ block_mounters(sdp, 0);
+ stack;
return FSCK_ERROR;
- } else if (replay_journals(sdp, preen, force_check, &clean_journals)) {
- if (!opts.no && preen_is_safe(sdp, preen, force_check))
- block_mounters(sdp, 0);
- stack;
- return FSCK_ERROR;
- }
- if (sdp->md.journals == clean_journals)
- *all_clean = 1;
- else {
- if (force_check || !preen)
+ }
+ if (sdp->md.journals == clean_journals)
+ *all_clean = 1;
+ else if (force_check || !preen)
log_notice( _("\nJournal recovery complete.\n"));
- }
- if (!force_check && *all_clean && preen)
- return FSCK_OK;
+ if (!force_check && *all_clean && preen)
+ return FSCK_OK;
+ }
if (init_system_inodes(sdp))
return FSCK_ERROR;
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index 289b062..adc87a4 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -368,14 +368,11 @@ static int check_entries(struct gfs2_inode *ip, struct gfs2_buffer_head *bh,
if (type == DIR_LINEAR) {
dent = (struct gfs2_dirent *)(bh->b_data + sizeof(struct gfs2_dinode));
- } else if (type == DIR_EXHASH) {
+ } else {
dent = (struct gfs2_dirent *)(bh->b_data + sizeof(struct gfs2_leaf));
log_debug( _("Checking leaf %llu (0x%llx)\n"),
(unsigned long long)bh->b_blocknr,
(unsigned long long)bh->b_blocknr);
- } else {
- log_err( _("Invalid directory type %d specified\n"), type);
- return -1;
}
prev = NULL;
@@ -465,7 +462,7 @@ static int check_entries(struct gfs2_inode *ip, struct gfs2_buffer_head *bh,
pass->private);
if (error < 0) {
stack;
- return -1;
+ return error;
}
}
}
@@ -529,7 +526,7 @@ int check_leaf(struct gfs2_inode *ip, int lindex, struct metawalk_fxns *pass,
if (pass->check_leaf_depth)
error = pass->check_leaf_depth(ip, *leaf_no, *ref_count, lbh);
- if (pass->check_leaf) {
+ if (error >= 0 && pass->check_leaf) {
error = pass->check_leaf(ip, *leaf_no, pass->private);
if (error == -EEXIST) {
log_info(_("Previous reference to leaf %lld (0x%llx) "
@@ -616,6 +613,8 @@ out:
(*ref_count) <<= (ip->i_di.di_depth - di_depth);
}
brelse(lbh);
+ if (error < 0)
+ return error;
return 0;
bad_leaf:
@@ -674,7 +673,7 @@ static void dir_leaf_reada(struct gfs2_inode *ip, uint64_t *tbl, unsigned hsize)
}
/* Checks exhash directory entries */
-static int check_leaf_blks(struct gfs2_inode *ip, struct metawalk_fxns *pass)
+int check_leaf_blks(struct gfs2_inode *ip, struct metawalk_fxns *pass)
{
int error = 0;
unsigned hsize = (1 << ip->i_di.di_depth);
@@ -801,6 +800,10 @@ static int check_leaf_blks(struct gfs2_inode *ip, struct metawalk_fxns *pass)
orig_ref_count, ref_count);
tbl_valid = 0;
}
+ if (error < 0) {
+ free(tbl);
+ return error;
+ }
if (!leaf.lf_next || error)
break;
leaf_no = leaf.lf_next;
diff --git a/gfs2/fsck/metawalk.h b/gfs2/fsck/metawalk.h
index aae9121..06345c3 100644
--- a/gfs2/fsck/metawalk.h
+++ b/gfs2/fsck/metawalk.h
@@ -11,6 +11,7 @@ struct metawalk_fxns;
extern int check_inode_eattr(struct gfs2_inode *ip,
struct metawalk_fxns *pass);
extern int check_metatree(struct gfs2_inode *ip, struct metawalk_fxns *pass);
+extern int check_leaf_blks(struct gfs2_inode *ip, struct metawalk_fxns *pass);
extern int check_dir(struct gfs2_sbd *sdp, uint64_t block,
struct metawalk_fxns *pass);
extern int check_linear_dir(struct gfs2_inode *ip, struct gfs2_buffer_head *bh,
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index 4348683..5342701 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -238,7 +238,7 @@ static int p1check_leaf(struct gfs2_inode *ip, uint64_t block, void *private)
if (q == gfs2_leaf_blk) /* If the previous reference also saw
this as a leaf, it was already
checked, so don't check again. */
- return -EEXIST;
+ return EEXIST; /* non-fatal */
}
fsck_blockmap_set(ip, block, _("directory leaf"), gfs2_leaf_blk);
return 0;
@@ -1532,9 +1532,9 @@ static int pass1_process_bitmap(struct gfs2_sbd *sdp, struct rgrp_tree *rgd, uin
if (q != gfs2_block_free) {
if (be32_to_cpu(check_magic) == GFS2_MAGIC &&
sdp->gfs1 && !is_inode) {
- log_debug("Block 0x%llx assumed to be "
- "previously processed GFS1 "
- "non-dinode metadata.\n",
+ log_debug(_("Block 0x%llx assumed to be "
+ "previously processed GFS1 "
+ "non-dinode metadata.\n"),
(unsigned long long)block);
brelse(bh);
continue;
9 years
gfs2-utils: RHEL7 - fsck.gfs2: Rebuild system files if they don't have the SYS bit set
by Andrew Price
Gitweb: http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=33aba2e2...
Commit: 33aba2e2eac3c7b920230eff868d14a1d48c1f8f
Parent: 1ecf5d89fa0ea0d707531e8e77305b4dc0bdc32b
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Fri Jan 9 12:27:57 2015 -0600
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Wed Apr 1 16:51:35 2015 +0100
fsck.gfs2: Rebuild system files if they don't have the SYS bit set
This patch checks for the GFS2_DIF_SYSTEM bit on system dinodes. If the
bit is not set, the dinode is assumed to be corrupt and rebuilt.
If the jindex is rebuilt, it needs to be re-read.
---
gfs2/fsck/pass1.c | 55 +++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 41 insertions(+), 14 deletions(-)
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index 2841b8c..4348683 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -27,6 +27,7 @@
#include "util.h"
#include "link.h"
#include "metawalk.h"
+#include "fs_recovery.h"
struct special_blocks gfs1_rindex_blks;
@@ -1241,7 +1242,8 @@ static int check_system_inode(struct gfs2_sbd *sdp,
struct gfs2_inode **sysinode,
const char *filename,
int builder(struct gfs2_sbd *sdp),
- enum gfs2_mark_block mark)
+ enum gfs2_mark_block mark,
+ struct gfs2_inode *sysdir, int needs_sysbit)
{
uint64_t iblock = 0;
struct dir_status ds = {0};
@@ -1282,6 +1284,24 @@ static int check_system_inode(struct gfs2_sbd *sdp,
if (mark == gfs2_inode_dir)
dirtree_insert((*sysinode)->i_di.di_num);
}
+ /* Make sure it's marked as a system file/directory */
+ if (needs_sysbit &&
+ !((*sysinode)->i_di.di_flags & GFS2_DIF_SYSTEM)) {
+ log_err( _("System inode %s is missing the 'system' "
+ "flag. It should be rebuilt.\n"), filename);
+ if (sysdir && query(_("Delete the corrupt %s system "
+ "inode? (y/n) "), filename)) {
+ inode_put(sysinode);
+ gfs2_dirent_del(sysdir, filename,
+ strlen(filename));
+ /* Set the blockmap (but not bitmap) back to
+ 'free' so that it gets checked like any
+ normal dinode. */
+ gfs2_blockmap_set(bl, iblock, gfs2_block_free);
+ log_err( _("Removed system inode \"%s\".\n"),
+ filename);
+ }
+ }
} else
log_info( _("System inode for '%s' is corrupt or missing.\n"),
filename);
@@ -1290,18 +1310,22 @@ static int check_system_inode(struct gfs2_sbd *sdp,
lost+found then, but we *need* our system inodes before we can
do any of that. */
if (!(*sysinode) || ds.q != mark) {
- log_err( _("Invalid or missing %s system inode (should be %d, "
- "is %d).\n"), filename, mark, ds.q);
+ log_err( _("Invalid or missing %s system inode (should be "
+ "'%s', is '%s').\n"), filename,
+ block_type_string(mark),
+ block_type_string(ds.q));
if (query(_("Create new %s system inode? (y/n) "), filename)) {
log_err( _("Rebuilding system file \"%s\"\n"),
filename);
error = builder(sdp);
if (error) {
- log_err( _("Error trying to rebuild system "
- "file %s: Cannot continue\n"),
+ log_err( _("Error rebuilding system "
+ "inode %s: Cannot continue\n"),
filename);
return error;
}
+ if (*sysinode == sdp->md.jiinode)
+ ji_update(sdp);
fsck_blockmap_set(*sysinode,
(*sysinode)->i_di.di_num.no_addr,
filename, mark);
@@ -1367,7 +1391,8 @@ static int check_system_inodes(struct gfs2_sbd *sdp)
sdp->master_dir->i_di.di_num.no_addr,
"master", gfs2_inode_dir);
if (check_system_inode(sdp, &sdp->master_dir, "master",
- build_master, gfs2_inode_dir)) {
+ build_master, gfs2_inode_dir,
+ NULL, 1)) {
stack;
return -1;
}
@@ -1377,39 +1402,41 @@ static int check_system_inodes(struct gfs2_sbd *sdp)
fsck_blockmap_set(sdp->md.rooti, sdp->md.rooti->i_di.di_num.no_addr,
"root", gfs2_inode_dir);
if (check_system_inode(sdp, &sdp->md.rooti, "root", build_root,
- gfs2_inode_dir)) {
+ gfs2_inode_dir, NULL, 0)) {
stack;
return -1;
}
if (!sdp->gfs1 &&
check_system_inode(sdp, &sdp->md.inum, "inum", build_inum,
- gfs2_inode_file)) {
+ gfs2_inode_file, sdp->master_dir, 1)) {
stack;
return -1;
}
if (check_system_inode(sdp, &sdp->md.statfs, "statfs", build_statfs,
- gfs2_inode_file)) {
+ gfs2_inode_file, sdp->master_dir, !sdp->gfs1)) {
stack;
return -1;
}
if (check_system_inode(sdp, &sdp->md.jiinode, "jindex", build_jindex,
- (sdp->gfs1 ? gfs2_inode_file : gfs2_inode_dir))) {
+ (sdp->gfs1 ? gfs2_inode_file : gfs2_inode_dir),
+ sdp->master_dir, !sdp->gfs1)) {
stack;
return -1;
}
if (check_system_inode(sdp, &sdp->md.riinode, "rindex", build_rindex,
- gfs2_inode_file)) {
+ gfs2_inode_file, sdp->master_dir, !sdp->gfs1)) {
stack;
return -1;
}
if (check_system_inode(sdp, &sdp->md.qinode, "quota", build_quota,
- gfs2_inode_file)) {
+ gfs2_inode_file, sdp->master_dir, !sdp->gfs1)) {
stack;
return -1;
}
if (!sdp->gfs1 &&
check_system_inode(sdp, &sdp->md.pinode, "per_node",
- build_per_node, gfs2_inode_dir)) {
+ build_per_node, gfs2_inode_dir,
+ sdp->master_dir, 1)) {
stack;
return -1;
}
@@ -1438,7 +1465,7 @@ static int check_system_inodes(struct gfs2_sbd *sdp)
sprintf(jname, "journal%d", sdp->md.journals);
if (check_system_inode(sdp, &sdp->md.journal[sdp->md.journals],
jname, build_a_journal,
- gfs2_inode_file)) {
+ gfs2_inode_file, sdp->md.jiinode, 1)) {
stack;
return -1;
}
9 years