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,