Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=9f…
Commit: 9f288bf60cc6d6b5285ba207d277a382c53f8460
Parent: 684770304edb7a23cc1d49a27553ba7d0035ec5a
Author: Bob Peterson <bob(a)ganesha.peterson>
AuthorDate: Mon Jan 25 14:43:14 2010 -0600
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Tue Jan 26 14:39:32 2010 -0600
fsck.gfs2: Don't add extended attrib blocks to list twice
This patch adds a simple check to pass1 where it is adding a
block to the list of blocks that contain an extended attribute.
If the block is already on the list, no need to add it again.
This can sometimes happen in duplicate reference situations and
other obscure code paths.
Since pass1 processes the file system sequentially by block number
it's enough to check against the block most recently added to the
list. This is a performance increase; early versions of this
code ran the entire linked list of special blocks. If the file
system was labelled for selinux, it could have millions of entries
on the linked list, causing an enormous slowdown.
rhbz#455300
---
gfs2/fsck/pass1.c | 26 ++++++++++++++++++++++----
1 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index 0a57939..aab44a9 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -494,6 +494,8 @@ static int finish_eattr_indir(struct gfs2_inode *ip, int leaf_pointers,
int leaf_pointer_errors, void *private)
{
struct block_count *bc = (struct block_count *) private;
+ osi_list_t *head;
+ struct special_blocks *b = NULL;
if (leaf_pointer_errors == leaf_pointers) /* All eas were bad */
return ask_remove_inode_eattr(ip, bc);
@@ -502,8 +504,17 @@ static int finish_eattr_indir(struct gfs2_inode *ip, int leaf_pointers,
(unsigned long long)ip->i_di.di_num.no_addr,
(unsigned long long)ip->i_di.di_num.no_addr);
/* Mark the inode as having an eattr in the block map
- so pass1c can check it. */
- gfs2_special_add(&ip->i_sbd->eattr_blocks, ip->i_di.di_num.no_addr);
+ so pass1c can check it. We may have previously added this inode
+ to the eattr_blocks list and if we did, it would be the first
+ one on the list. So check that one only (to save time) and
+ if that one matches, no need to add it again. */
+ if (!osi_list_empty(&ip->i_sbd->eattr_blocks.list)) {
+ head = &ip->i_sbd->eattr_blocks.list;
+ b = osi_list_entry(head->next, struct special_blocks, list);
+ }
+ if (!b || b->block != ip->i_di.di_num.no_addr)
+ gfs2_special_add(&ip->i_sbd->eattr_blocks,
+ ip->i_di.di_num.no_addr);
if (!leaf_pointer_errors)
return 0;
log_err( _("Inode %lld (0x%llx) has recoverable indirect "
@@ -624,6 +635,8 @@ static int check_eattr_leaf(struct gfs2_inode *ip, uint64_t block,
void *private)
{
struct gfs2_sbd *sdp = ip->i_sbd;
+ osi_list_t *head;
+ struct special_blocks *b = NULL;
/* This inode contains an eattr - it may be invalid, but the
* eattr attributes points to a non-zero block.
@@ -634,8 +647,13 @@ static int check_eattr_leaf(struct gfs2_inode *ip, uint64_t block,
"block(s) attached.\n"),
(unsigned long long)ip->i_di.di_num.no_addr,
(unsigned long long)ip->i_di.di_num.no_addr);
- gfs2_special_add(&sdp->eattr_blocks, ip->i_di.di_num.no_addr);
- if(gfs2_check_range(sdp, block)) {
+ if (!osi_list_empty(&ip->i_sbd->eattr_blocks.list)) {
+ head = &ip->i_sbd->eattr_blocks.list;
+ b = osi_list_entry(head->next, struct special_blocks, list);
+ }
+ if (!b || b->block != ip->i_di.di_num.no_addr)
+ gfs2_special_add(&sdp->eattr_blocks, ip->i_di.di_num.no_addr);
+ if (gfs2_check_range(sdp, block)) {
log_warn( _("Inode #%llu (0x%llx): Extended Attribute leaf "
"block #%llu (0x%llx) is out of range.\n"),
(unsigned long long)ip->i_di.di_num.no_addr,
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=68…
Commit: 684770304edb7a23cc1d49a27553ba7d0035ec5a
Parent: 43632210b4fc2121005cb8ca5bbe1d10cdc97da6
Author: Bob Peterson <bob(a)ganesha.peterson>
AuthorDate: Mon Jan 25 14:34:16 2010 -0600
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Tue Jan 26 14:39:32 2010 -0600
fsck.gfs2: Free metadata list memory we don't need
This patch modifies function check_metatree so that it frees up
metadata from memory for heights it's no longer interested in.
This patches a memory leak.
rhbz#455300
---
gfs2/fsck/metawalk.c | 15 +++++++++++++++
1 files changed, 15 insertions(+), 0 deletions(-)
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index 4a6651f..4ab2603 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -1298,6 +1298,21 @@ int check_metatree(struct gfs2_inode *ip, struct metawalk_fxns *pass)
return error;
}
+ /* Free the metalist buffers from heights we don't need to check.
+ For the rest we'll free as we check them to save time.
+ metalist[0] will only have the dinode bh, so we can skip it. */
+ for (i = 1; i < height - 1; i++) {
+ list = &metalist[i];
+ while (!osi_list_empty(list)) {
+ bh = osi_list_entry(list->next,
+ struct gfs2_buffer_head, b_altlist);
+ if (bh == ip->i_bh)
+ osi_list_del(&bh->b_altlist);
+ else
+ brelse(bh);
+ }
+ }
+
/* check data blocks */
list = &metalist[height - 1];
if (ip->i_di.di_blocks > COMFORTABLE_BLKS)
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=43…
Commit: 43632210b4fc2121005cb8ca5bbe1d10cdc97da6
Parent: fbf9933c3626b3e670fec6f2d218eec3c36d81bc
Author: Bob Peterson <bob(a)ganesha.peterson>
AuthorDate: Mon Jan 25 14:27:31 2010 -0600
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Tue Jan 26 14:39:32 2010 -0600
fsck.gfs2: Force intermediate lost+found inode updates
This patch forces the lost+found dinode to be rewritten every time
an orphan inode is moved into lost+found. That way, if the user
interrupts fsck.gfs2 during pass4, they won't be left with a
lost+found dinode with an invalid number of blocks, links and so
forth.
rhbz#455300
---
gfs2/fsck/lost_n_found.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/gfs2/fsck/lost_n_found.c b/gfs2/fsck/lost_n_found.c
index c6a8a6e..c5051f9 100644
--- a/gfs2/fsck/lost_n_found.c
+++ b/gfs2/fsck/lost_n_found.c
@@ -183,5 +183,7 @@ int add_inode_to_lf(struct gfs2_inode *ip){
log_notice( _("Added inode #%llu (0x%llx) to lost+found dir\n"),
(unsigned long long)ip->i_di.di_num.no_addr,
(unsigned long long)ip->i_di.di_num.no_addr);
+ gfs2_dinode_out(&lf_dip->i_di, lf_dip->i_bh);
+ bwrite(lf_dip->i_bh);
return 0;
}
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=fb…
Commit: fbf9933c3626b3e670fec6f2d218eec3c36d81bc
Parent: 1ab1e80fa38db9de3d9146ee1a5845c91c007970
Author: Bob Peterson <bob(a)ganesha.peterson>
AuthorDate: Mon Jan 25 13:52:20 2010 -0600
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Tue Jan 26 14:39:32 2010 -0600
fsck.gfs2: invalidate invalid mode inodes
When fsck.gfs2 encountered a dinode that had an invalid type
(file, directory, socket, etc), it marked that block in the blockmap
as an invalid block. That caused pass2 to delete it AND its metadata.
Since the metadata had not been previously processed, it would be
deleted wholesale. That's okay for most cases, but if there was
a duplicate reference to any of those metadata blocks, pass2 would
not realize it and free the block anyway, out from under the valid
reference. In other words, the valid reference to the block would
remain intact but the block was freed in the bitmap because it was
associated with the dinode that had an unknown type. That means big
time corruption because future block allocations could then reuse the
freed metadata, once again causing another duplicate block reference.
This patch invalidates the metadata associated with dinodes that
do not have a valid inode type. That causes all of its metadata to
be processed and duplicate references are put on the new invalid
references list. Later, in pass1b, the duplicate block references
are resolved and the last remaining reference is left in a valid
state. And pass2 had no more cause to free the block.
rhbz#455300
---
gfs2/fsck/pass1.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 100 insertions(+), 0 deletions(-)
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index 8ce1206..0a57939 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -59,6 +59,19 @@ static int check_extended_leaf_eattr(struct gfs2_inode *ip, uint64_t *data_ptr,
void *private);
static int finish_eattr_indir(struct gfs2_inode *ip, int leaf_pointers,
int leaf_pointer_errors, void *private);
+static int invalidate_metadata(struct gfs2_inode *ip, uint64_t block,
+ struct gfs2_buffer_head **bh, void *private);
+static int invalidate_leaf(struct gfs2_inode *ip, uint64_t block,
+ struct gfs2_buffer_head *bh, void *private);
+static int invalidate_data(struct gfs2_inode *ip, uint64_t block,
+ void *private);
+static int invalidate_eattr_indir(struct gfs2_inode *ip, uint64_t block,
+ uint64_t parent,
+ struct gfs2_buffer_head **bh,
+ void *private);
+static int invalidate_eattr_leaf(struct gfs2_inode *ip, uint64_t block,
+ uint64_t parent, struct gfs2_buffer_head **bh,
+ void *private);
struct metawalk_fxns pass1_fxns = {
.private = NULL,
@@ -79,6 +92,15 @@ struct metawalk_fxns undo_fxns = {
.check_data = undo_check_data,
};
+struct metawalk_fxns invalidate_fxns = {
+ .private = NULL,
+ .check_metalist = invalidate_metadata,
+ .check_data = invalidate_data,
+ .check_leaf = invalidate_leaf,
+ .check_eattr_indir = invalidate_eattr_indir,
+ .check_eattr_leaf = invalidate_eattr_leaf,
+};
+
static int leaf(struct gfs2_inode *ip, uint64_t block,
struct gfs2_buffer_head *bh, void *private)
{
@@ -669,6 +691,72 @@ static int check_eattr_entries(struct gfs2_inode *ip,
}
/**
+ * mark_block_invalid - mark blocks associated with an inode as invalid
+ * unless the block is a duplicate.
+ *
+ * An "invalid" block is now considered free in the bitmap, and pass2 will
+ * delete any invalid blocks. This is nearly identical to function
+ * delete_block_if_notdup.
+ */
+static int mark_block_invalid(struct gfs2_inode *ip, uint64_t block,
+ enum dup_ref_type reftype, const char *btype)
+{
+ uint8_t q;
+
+ if (gfs2_check_range(ip->i_sbd, block) != 0)
+ return -EFAULT;
+
+ q = block_type(block);
+ if (q != gfs2_block_free) {
+ add_duplicate_ref(ip, block, reftype, 0, INODE_INVALID);
+ log_info( _("%s block %lld (0x%llx), part of inode "
+ "%lld (0x%llx), was free so the invalid "
+ "reference is ignored.\n"),
+ btype, (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 0;
+ }
+ fsck_blockmap_set(ip, block, btype, gfs2_meta_inval);
+ return 0;
+}
+
+static int invalidate_metadata(struct gfs2_inode *ip, uint64_t block,
+ struct gfs2_buffer_head **bh, void *private)
+{
+ return mark_block_invalid(ip, block, ref_as_meta, _("metadata"));
+}
+
+static int invalidate_leaf(struct gfs2_inode *ip, uint64_t block,
+ struct gfs2_buffer_head *bh, void *private)
+{
+ return mark_block_invalid(ip, block, ref_as_meta, _("leaf"));
+}
+
+static int invalidate_data(struct gfs2_inode *ip, uint64_t block,
+ void *private)
+{
+ return mark_block_invalid(ip, block, ref_as_data, _("data"));
+}
+
+static int invalidate_eattr_indir(struct gfs2_inode *ip, uint64_t block,
+ uint64_t parent,
+ struct gfs2_buffer_head **bh, void *private)
+{
+ return mark_block_invalid(ip, block, ref_as_ea,
+ _("indirect extended attribute"));
+}
+
+static int invalidate_eattr_leaf(struct gfs2_inode *ip, uint64_t block,
+ uint64_t parent, struct gfs2_buffer_head **bh,
+ void *private)
+{
+ return mark_block_invalid(ip, block, ref_as_ea,
+ _("extended attribute"));
+}
+
+/**
* Check for massive amounts of pointer corruption. If the block has
* lots of out-of-range pointers, we can't trust any of the pointers.
* For example, a stray pointer with a value of 0x1d might be
@@ -878,6 +966,18 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh,
}
break;
default:
+ /* We found a dinode that has an invalid mode, so we can't
+ tell if it's a data file, directory or a socket.
+ Regardless, we have to invalidate its metadata in case there
+ are duplicate blocks referenced. If we don't call
+ check_metatree, the blocks it references will be deleted
+ wholesale by pass2, and if any of those blocks are
+ duplicates--referenced by another dinode for some reason--
+ we will mark it free, even though it's in use. In other
+ words, we would introduce file system corruption. So we
+ need to keep track of the fact that it's invalid and
+ skip parts that we can't be sure of based on dinode type. */
+ check_metatree(ip, &invalidate_fxns);
if (fsck_blockmap_set(ip, block, _("invalid mode"),
gfs2_inode_invalid)) {
stack;
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=3f…
Commit: 3f3635066f6cc191bf77576ee6c6622fee5b446c
Parent: cf82aa427614d6bae9216d78efe1782bfee336ec
Author: Bob Peterson <bob(a)ganesha.peterson>
AuthorDate: Mon Jan 25 12:47:27 2010 -0600
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Tue Jan 26 14:39:32 2010 -0600
fsck.gfs2: Make pass1 undo its work for unrecoverable inodes
When pass1 discovers a dinode that has so much damage it finally
gives up on it, it was invalidating all the inode's metadata blocks.
The problem with with doing that is that it often gave up on the
dinode half-way through processing its metadata, so some of the
metadata blocks were marked as some block type n the blockmap (such
as indirect blocks or duplicate reference) while the unprocessed
blocks were not marked at all, leaving them unaccounted for.
Later, marking them as invalid caused subsequent processing of
other dinodes that referenced those blocks to think they were
duplicate references, often with disasterous consequences. Often
the duplicate processing code in pass1b would favor the first
("invalidated") reference and delete the second ("good") reference,
which means it introduced corruption. The proper thing to do is
to undo its blockmap designations, and stop at the same place it
did when it gave up on the dinode. This patch introduces a new
set of "undo" metadata processing functions to accomplish this task.
These undo_check_metalist and related functions MUST be kept in sync
with pass1's normal pass1_fxns functions. In other words, they must
stop at the same block of metadata and return the same error to
ensure anything that pass1_fxns does is properly undone by the
corresponding undo functions.
rhbz#455300
---
gfs2/fsck/pass1.c | 197 +++++++++++++++++++++++++++++++++++++++++------------
1 files changed, 154 insertions(+), 43 deletions(-)
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index 2f6782a..a993466 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -36,7 +36,11 @@ static int leaf(struct gfs2_inode *ip, uint64_t block,
struct gfs2_buffer_head *bh, void *private);
static int check_metalist(struct gfs2_inode *ip, uint64_t block,
struct gfs2_buffer_head **bh, void *private);
+static int undo_check_metalist(struct gfs2_inode *ip, uint64_t block,
+ struct gfs2_buffer_head **bh, void *private);
static int check_data(struct gfs2_inode *ip, uint64_t block, void *private);
+static int undo_check_data(struct gfs2_inode *ip, uint64_t block,
+ void *private);
static int check_eattr_indir(struct gfs2_inode *ip, uint64_t indirect,
uint64_t parent, struct gfs2_buffer_head **bh,
void *private);
@@ -69,6 +73,12 @@ struct metawalk_fxns pass1_fxns = {
.finish_eattr_indir = finish_eattr_indir,
};
+struct metawalk_fxns undo_fxns = {
+ .private = NULL,
+ .check_metalist = undo_check_metalist,
+ .check_data = undo_check_data,
+};
+
static int leaf(struct gfs2_inode *ip, uint64_t block,
struct gfs2_buffer_head *bh, void *private)
{
@@ -148,6 +158,62 @@ static int check_metalist(struct gfs2_inode *ip, uint64_t block,
return 0;
}
+static int undo_check_metalist(struct gfs2_inode *ip, uint64_t block,
+ struct gfs2_buffer_head **bh, void *private)
+{
+ struct duptree *d;
+ int found_dup = 0, iblk_type;
+ struct gfs2_buffer_head *nbh;
+ struct block_count *bc = (struct block_count *)private;
+
+ *bh = NULL;
+
+ if (gfs2_check_range(ip->i_sbd, block)){ /* blk outside of FS */
+ fsck_blockmap_set(ip, ip->i_di.di_num.no_addr,
+ _("itself"), gfs2_block_free);
+ return 1;
+ }
+ if (S_ISDIR(ip->i_di.di_mode))
+ iblk_type = GFS2_METATYPE_JD;
+ else
+ iblk_type = GFS2_METATYPE_IN;
+
+ d = dupfind(block);
+ if (d) {
+ log_err( _("Reversing duplicate status of block %llu (0x%llx) "
+ "referenced as metadata in indirect block for "
+ "dinode %llu (0x%llx)\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);
+ d->refs--; /* one less reference */
+ if (d->refs == 1)
+ dup_delete(d);
+ found_dup = 1;
+ }
+ nbh = bread(ip->i_sbd, block);
+
+ if (gfs2_check_meta(nbh, iblk_type)) {
+ if(!found_dup) {
+ fsck_blockmap_set(ip, block, _("bad indirect"),
+ gfs2_block_free);
+ brelse(nbh);
+ return 1;
+ }
+ brelse(nbh);
+ } else /* blk check ok */
+ *bh = nbh;
+
+ bc->indir_count--;
+ if (found_dup)
+ return 1; /* don't process the metadata again */
+ else
+ fsck_blockmap_set(ip, block, _("bad indirect"),
+ gfs2_block_free);
+ return 0;
+}
+
static int check_data(struct gfs2_inode *ip, uint64_t block, void *private)
{
uint8_t q;
@@ -198,12 +264,87 @@ static int check_data(struct gfs2_inode *ip, uint64_t block, void *private)
return error;
}
-static int remove_inode_eattr(struct gfs2_inode *ip, struct block_count *bc,
- int duplicate)
+static int undo_check_data(struct gfs2_inode *ip, uint64_t block,
+ void *private)
{
- if (!duplicate)
- fsck_blockmap_set(ip, ip->i_di.di_eattr, _("deleted eattr"),
+ struct duptree *d;
+ struct block_count *bc = (struct block_count *) private;
+
+ if (gfs2_check_range(ip->i_sbd, block)) {
+ /* Mark the owner of this block with the bad_block
+ * designator so we know to check it for out of range
+ * blocks later */
+ fsck_blockmap_set(ip, ip->i_di.di_num.no_addr,
+ _("bad (out of range) data"),
gfs2_block_free);
+ return 1;
+ }
+ d = dupfind(block);
+ if (d) {
+ log_err( _("Reversing duplicate status of block %llu (0x%llx) "
+ "referenced as data by dinode %llu (0x%llx)\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);
+ d->refs--; /* one less reference */
+ if (d->refs == 1)
+ dup_delete(d);
+ bc->data_count--;
+ return 1;
+ }
+ fsck_blockmap_set(ip, block, _("data"), gfs2_block_free);
+ bc->data_count--;
+ return 0;
+}
+
+static int remove_inode_eattr(struct gfs2_inode *ip, struct block_count *bc)
+{
+ struct duptree *dt;
+ struct inode_with_dups *id;
+ osi_list_t *ref;
+ int moved = 0;
+
+ /* If it's a duplicate reference to the block, we need to check
+ if the reference is on the valid or invalid inodes list.
+ If it's on the valid inode's list, move it to the invalid
+ inodes list. The reason is simple: This inode, although
+ valid, has an now-invalid reference, so we should not give
+ this reference preferential treatment over others. */
+ dt = dupfind(ip->i_di.di_eattr);
+ if (dt) {
+ osi_list_foreach(ref, &dt->ref_inode_list) {
+ id = osi_list_entry(ref, struct inode_with_dups, list);
+ if (id->block_no == ip->i_di.di_num.no_addr) {
+ log_debug( _("Moving inode %lld (0x%llx)'s "
+ "duplicate reference to %lld "
+ "(0x%llx) from the valid to the "
+ "invalid reference list.\n"),
+ (unsigned long long)
+ ip->i_di.di_num.no_addr,
+ (unsigned long long)
+ ip->i_di.di_num.no_addr,
+ (unsigned long long)
+ ip->i_di.di_eattr,
+ (unsigned long long)
+ ip->i_di.di_eattr);
+ /* Move from the normal to the invalid list */
+ osi_list_del(&id->list);
+ osi_list_add_prev(&id->list,
+ &dt->ref_invinode_list);
+ moved = 1;
+ break;
+ }
+ }
+ if (!moved)
+ log_debug( _("Duplicate reference to %lld "
+ "(0x%llx) not moved.\n"),
+ (unsigned long long)ip->i_di.di_eattr,
+ (unsigned long long)ip->i_di.di_eattr);
+ } else {
+ delete_block(ip, ip->i_di.di_eattr, NULL,
+ "extended attribute", NULL);
+ }
ip->i_di.di_eattr = 0;
bc->ea_count = 0;
ip->i_di.di_blocks = 1 + bc->indir_count + bc->data_count;
@@ -219,8 +360,7 @@ static int ask_remove_inode_eattr(struct gfs2_inode *ip,
"errors.\n"), (unsigned long long)ip->i_di.di_num.no_addr,
(unsigned long long)ip->i_di.di_num.no_addr);
if (query( _("Clear all Extended Attributes from the inode? (y/n) "))){
- if (!remove_inode_eattr(ip, bc,
- is_duplicate(ip->i_di.di_eattr)))
+ if (!remove_inode_eattr(ip, bc))
log_err( _("Extended attributes were removed.\n"));
else
log_err( _("Unable to remove inode eattr pointer; "
@@ -250,7 +390,7 @@ static int clear_eas(struct gfs2_inode *ip, struct block_count *bc,
(unsigned long long)block, (unsigned long long)block);
if (query( _("Clear the bad Extended Attribute? (y/n) "))) {
if (block == ip->i_di.di_eattr) {
- remove_inode_eattr(ip, bc, duplicate);
+ remove_inode_eattr(ip, bc);
log_err( _("The bad extended attribute was "
"removed.\n"));
} else if (!duplicate) {
@@ -524,34 +664,6 @@ static int check_eattr_entries(struct gfs2_inode *ip,
return 0;
}
-static int clear_metalist(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head **bh, void *private)
-{
- *bh = NULL;
-
- if(!is_duplicate(block))
- fsck_blockmap_set(ip, block, _("cleared metadata"),
- gfs2_block_free);
- return 0;
-}
-
-static int clear_data(struct gfs2_inode *ip, uint64_t block, void *private)
-{
- if(!is_duplicate(block))
- fsck_blockmap_set(ip, block, _("cleared data"),
- gfs2_block_free);
- return 0;
-}
-
-static int clear_leaf(struct gfs2_inode *ip, uint64_t block,
- struct gfs2_buffer_head *bh, void *private)
-{
- if(!is_duplicate(block))
- fsck_blockmap_set(ip, block, _("cleared directory leaf"),
- gfs2_block_free);
- return 0;
-}
-
/**
* Check for massive amounts of pointer corruption. If the block has
* lots of out-of-range pointers, we can't trust any of the pointers.
@@ -650,7 +762,6 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh,
struct gfs2_inode *ip;
int error;
struct block_count bc = {0};
- struct metawalk_fxns invalidate_metatree = {0};
long bad_pointers;
q = block_type(block);
@@ -809,14 +920,14 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh,
"errors; invalidating.\n"),
(unsigned long long)ip->i_di.di_num.no_addr,
(unsigned long long)ip->i_di.di_num.no_addr);
- invalidate_metatree.check_metalist = clear_metalist;
- invalidate_metatree.check_data = clear_data;
- invalidate_metatree.check_leaf = clear_leaf;
-
- /* FIXME: Must set all leaves invalid as well */
- check_metatree(ip, &invalidate_metatree);
+ undo_fxns.private = &bc;
+ check_metatree(ip, &undo_fxns);
+ /* If we undo the metadata accounting, including metadatas
+ duplicate block status, we need to make sure later passes
+ don't try to free up the metadata referenced by this inode.
+ Therefore we mark the inode as free space. */
fsck_blockmap_set(ip, ip->i_di.di_num.no_addr,
- _("corrupt"), gfs2_meta_inval);
+ _("corrupt"), gfs2_block_free);
fsck_inode_put(&ip);
return 0;
}
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=8e…
Commit: 8e4f539322c240851e5bcf906e54905be9e0a924
Parent: 7bd37e30f2dd4a54283ac57f0df003840fe010d7
Author: Bob Peterson <bob(a)ganesha.peterson>
AuthorDate: Mon Jan 25 16:23:19 2010 -0600
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Tue Jan 26 14:39:31 2010 -0600
Eliminate unnecessary block_list from gfs2_edit
There is no need for a blockmap in gfs2_edit's savemeta function
so this patch eliminates it.
rhbz#455300
---
gfs2/edit/savemeta.c | 18 +-----------------
1 files changed, 1 insertions(+), 17 deletions(-)
diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c
index 3e7ec7e..6df3a4b 100644
--- a/gfs2/edit/savemeta.c
+++ b/gfs2/edit/savemeta.c
@@ -35,7 +35,6 @@ struct saved_metablock {
struct saved_metablock *savedata;
struct gfs2_buffer_head *savebh;
uint64_t last_fs_block, last_reported_block, blks_saved, total_out, pct;
-struct gfs2_bmap *blocklist = NULL;
uint64_t journal_blocks[MAX_JOURNALS_SAVED];
uint64_t gfs1_journal_size = 0; /* in blocks */
int journals_found = 0;
@@ -499,7 +498,6 @@ void savemeta(char *out_fn, int saveoption)
int out_fd;
int slow;
osi_list_t *tmp;
- uint64_t memreq;
int rgcount;
uint64_t jindex_block;
struct gfs2_buffer_head *lbh;
@@ -599,12 +597,6 @@ void savemeta(char *out_fn, int saveoption)
printf("Done.\n\n");
fflush(stdout);
}
- if (!slow) {
- blocklist = gfs2_bmap_create(&sbd, last_fs_block + 1,
- &memreq);
- if (!blocklist)
- slow = TRUE;
- }
get_journal_inode_blocks();
if (!slow) {
/* Save off the superblock */
@@ -631,7 +623,7 @@ void savemeta(char *out_fn, int saveoption)
for (tmp = sbd.rglist.next; tmp != &sbd.rglist;
tmp = tmp->next){
struct rgrp_list *rgd;
- int i, first;
+ int first;
rgd = osi_list_entry(tmp, struct rgrp_list, list);
slow = gfs2_rgrp_read(&sbd, rgd);
@@ -641,12 +633,6 @@ void savemeta(char *out_fn, int saveoption)
(unsigned long long)rgd->ri.ri_addr,
(unsigned long long)rgd->ri.ri_addr,
rgd->ri.ri_length);
- for (i = 0; i < rgd->ri.ri_length; i++) {
- if(gfs2_blockmap_set(blocklist,
- rgd->ri.ri_addr + i,
- gfs2_meta_other))
- break;
- }
first = 1;
/* Save off the rg and bitmaps */
for (block = rgd->ri.ri_addr;
@@ -685,8 +671,6 @@ void savemeta(char *out_fn, int saveoption)
}
}
/* Clean up */
- if (blocklist)
- gfs2_bmap_destroy(&sbd, blocklist);
/* There may be a gap between end of file system and end of device */
/* so we tell the user that we've processed everything. */
block = last_fs_block;