Gitweb:
http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=f8203271...
Commit: f8203271fac38964850c36f7bb8fb363faeb75f9
Parent: b605ea0036696513db3b377f23576c3bbda5e611
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Thu Mar 17 15:36:46 2016 -0400
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Mon May 9 10:50:12 2016 -0500
fsck.gfs2: eliminate fsck_blockmap_set from check_eattr_entries
Before this patch, metawalk function check_eattr_entries was calling
function fsck_blockmap_set, but only on error conditions.
This patch makes it the caller's responsibility. Since pass1 called
check_eattr_entries, it needed to set the blockmap and bitmap, so
that's now included in the pass1->check_eattr_extentry caller.
Subsequent passes don't need to set the blockmap, but they do need
to set the bitmap. That's also moved to the pass->check_eattr_extentry
but in reality, it's only delete_eattr_extentry that needs to do this.
The only other caller is check_eattr_extentry_refs in pass1b, but
that's a special case in which we don't want to delete the eattrs.
Signed-off-by: Bob Peterson <rpeterso(a)redhat.com>
---
gfs2/fsck/afterpass1_common.c | 32 ++++++++++++++++++++++++++---
gfs2/fsck/afterpass1_common.h | 4 ++-
gfs2/fsck/metawalk.c | 43 ++++++----------------------------------
gfs2/fsck/metawalk.h | 3 +-
gfs2/fsck/pass1.c | 39 ++++++++++++++++++++++++++++++++----
gfs2/fsck/pass1b.c | 9 +++++++-
6 files changed, 82 insertions(+), 48 deletions(-)
diff --git a/gfs2/fsck/afterpass1_common.c b/gfs2/fsck/afterpass1_common.c
index 36646f8..bdea242 100644
--- a/gfs2/fsck/afterpass1_common.c
+++ b/gfs2/fsck/afterpass1_common.c
@@ -260,13 +260,37 @@ int delete_eattr_entry(struct gfs2_inode *ip, struct
gfs2_buffer_head *leaf_bh,
return 0;
}
-int delete_eattr_extentry(struct gfs2_inode *ip, uint64_t *ea_data_ptr,
- struct gfs2_buffer_head *leaf_bh,
+int delete_eattr_extentry(struct gfs2_inode *ip, int i, uint64_t *ea_data_ptr,
+ struct gfs2_buffer_head *leaf_bh, uint32_t tot_ealen,
struct gfs2_ea_header *ea_hdr,
struct gfs2_ea_header *ea_hdr_prev, void *private)
{
uint64_t block = be64_to_cpu(*ea_data_ptr);
+ int error;
- return delete_block_if_notdup(ip, block, NULL, _("extended attribute"),
- NULL, private);
+ error = delete_block_if_notdup(ip, block, NULL,
+ _("extended attribute"), NULL, private);
+ if (error) {
+ log_err(_("Bad extended attribute found at block %lld "
+ "(0x%llx)"),
+ (unsigned long long)be64_to_cpu(*ea_data_ptr),
+ (unsigned long long)be64_to_cpu(*ea_data_ptr));
+ if (query( _("Repair the bad Extended Attribute? (y/n) "))) {
+ ea_hdr->ea_num_ptrs = i;
+ ea_hdr->ea_data_len = cpu_to_be32(tot_ealen);
+ *ea_data_ptr = 0;
+ bmodified(leaf_bh);
+ /* Endianness doesn't matter in this case because it's
+ a single byte. */
+ fsck_bitmap_set(ip, ip->i_di.di_eattr,
+ _("extended attribute"),
+ ip->i_sbd->gfs1 ? GFS2_BLKST_DINODE :
+ GFS2_BLKST_USED);
+ log_err( _("The EA was fixed.\n"));
+ } else {
+ error = 1;
+ log_err( _("The bad EA was not fixed.\n"));
+ }
+ }
+ return error;
}
diff --git a/gfs2/fsck/afterpass1_common.h b/gfs2/fsck/afterpass1_common.h
index 2a422c7..8b345ee 100644
--- a/gfs2/fsck/afterpass1_common.h
+++ b/gfs2/fsck/afterpass1_common.h
@@ -19,8 +19,10 @@ extern int delete_eattr_entry(struct gfs2_inode *ip,
struct gfs2_ea_header *ea_hdr,
struct gfs2_ea_header *ea_hdr_prev,
void *private);
-extern int delete_eattr_extentry(struct gfs2_inode *ip, uint64_t *ea_data_ptr,
+extern int delete_eattr_extentry(struct gfs2_inode *ip, int i,
+ uint64_t *ea_data_ptr,
struct gfs2_buffer_head *leaf_bh,
+ uint32_t tot_ealen,
struct gfs2_ea_header *ea_hdr,
struct gfs2_ea_header *ea_hdr_prev,
void *private);
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index 529c86d..ac345f2 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -854,7 +854,7 @@ static int check_eattr_entries(struct gfs2_inode *ip,
struct gfs2_ea_header *ea_hdr, *ea_hdr_prev = NULL;
uint64_t *ea_data_ptr = NULL;
int i;
- int error = 0;
+ int error = 0, err;
uint32_t offset = (uint32_t)sizeof(struct gfs2_meta_header);
if (!pass->check_eattr_entry)
@@ -891,41 +891,12 @@ static int check_eattr_entries(struct gfs2_inode *ip,
** reuse........... */
for(i = 0; i < ea_hdr->ea_num_ptrs; i++){
- if (pass->check_eattr_extentry(ip,
- ea_data_ptr,
- bh, ea_hdr,
- ea_hdr_prev,
- pass->private)) {
- log_err(_("Bad extended attribute "
- "found at block %lld "
- "(0x%llx)"),
- (unsigned long long)
- be64_to_cpu(*ea_data_ptr),
- (unsigned long long)
- be64_to_cpu(*ea_data_ptr));
- if (query( _("Repair the bad Extended "
- "Attribute? (y/n) "))) {
- ea_hdr->ea_num_ptrs = i;
- ea_hdr->ea_data_len =
- cpu_to_be32(tot_ealen);
- *ea_data_ptr = 0;
- bmodified(bh);
- /* Endianness doesn't matter
- in this case because it's
- a single byte. */
- fsck_blockmap_set(ip,
- ip->i_di.di_eattr,
- _("extended attribute"),
- sdp->gfs1 ? GFS2_BLKST_DINODE :
- GFS2_BLKST_USED);
- log_err( _("The EA was "
- "fixed.\n"));
- } else {
- error = 1;
- log_err( _("The bad EA was "
- "not fixed.\n"));
- }
- }
+ err = pass->check_eattr_extentry(ip, i,
+ ea_data_ptr, bh, tot_ealen,
+ ea_hdr, ea_hdr_prev,
+ pass->private);
+ if (err)
+ error = err;
tot_ealen += sdp->sd_sb.sb_bsize -
sizeof(struct gfs2_meta_header);
ea_data_ptr++;
diff --git a/gfs2/fsck/metawalk.h b/gfs2/fsck/metawalk.h
index d2f0d97..e47a871 100644
--- a/gfs2/fsck/metawalk.h
+++ b/gfs2/fsck/metawalk.h
@@ -108,9 +108,10 @@ struct metawalk_fxns {
struct gfs2_ea_header *ea_hdr,
struct gfs2_ea_header *ea_hdr_prev,
void *private);
- int (*check_eattr_extentry) (struct gfs2_inode *ip,
+ int (*check_eattr_extentry) (struct gfs2_inode *ip, int i,
uint64_t *ea_data_ptr,
struct gfs2_buffer_head *leaf_bh,
+ uint32_t tot_ealen,
struct gfs2_ea_header *ea_hdr,
struct gfs2_ea_header *ea_hdr_prev,
void *private);
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index 0ae842e..aae5a06 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -59,8 +59,10 @@ static int check_eattr_entries(struct gfs2_inode *ip,
struct gfs2_ea_header *ea_hdr,
struct gfs2_ea_header *ea_hdr_prev,
void *private);
-static int check_extended_leaf_eattr(struct gfs2_inode *ip, uint64_t *data_ptr,
+static int check_extended_leaf_eattr(struct gfs2_inode *ip, int i,
+ uint64_t *data_ptr,
struct gfs2_buffer_head *leaf_bh,
+ uint32_t tot_ealen,
struct gfs2_ea_header *ea_hdr,
struct gfs2_ea_header *ea_hdr_prev,
void *private);
@@ -789,8 +791,10 @@ static int check_ealeaf_block(struct gfs2_inode *ip, uint64_t block,
int btype,
*
* Returns: 0 if correct[able], -1 if removal is needed
*/
-static int check_extended_leaf_eattr(struct gfs2_inode *ip, uint64_t *data_ptr,
+static int check_extended_leaf_eattr(struct gfs2_inode *ip, int i,
+ uint64_t *data_ptr,
struct gfs2_buffer_head *leaf_bh,
+ uint32_t tot_ealen,
struct gfs2_ea_header *ea_hdr,
struct gfs2_ea_header *ea_hdr_prev,
void *private)
@@ -798,7 +802,7 @@ static int check_extended_leaf_eattr(struct gfs2_inode *ip, uint64_t
*data_ptr,
uint64_t el_blk = be64_to_cpu(*data_ptr);
struct gfs2_sbd *sdp = ip->i_sbd;
struct gfs2_buffer_head *bh = NULL;
- int error;
+ int error = 0;
if (!valid_block(sdp, el_blk)) {
log_err( _("Inode #%llu (0x%llx): Extended Attribute block "
@@ -813,11 +817,36 @@ static int check_extended_leaf_eattr(struct gfs2_inode *ip, uint64_t
*data_ptr,
fsck_blockmap_set(ip, ip->i_di.di_eattr,
_("bad (out of range) Extended Attribute "),
GFS2_BLKST_UNLINKED);
- return 1;
+ error = 1;
+ } else {
+ error = check_ealeaf_block(ip, el_blk, GFS2_METATYPE_ED, &bh,
+ private);
}
- error = check_ealeaf_block(ip, el_blk, GFS2_METATYPE_ED, &bh, private);
if (bh)
brelse(bh);
+ if (error) {
+ log_err(_("Bad extended attribute found at block %lld "
+ "(0x%llx)"),
+ (unsigned long long)be64_to_cpu(*data_ptr),
+ (unsigned long long)be64_to_cpu(*data_ptr));
+ if (query( _("Repair the bad Extended Attribute? (y/n) "))) {
+ ea_hdr->ea_num_ptrs = i;
+ ea_hdr->ea_data_len = cpu_to_be32(tot_ealen);
+ *data_ptr = 0;
+ bmodified(leaf_bh);
+ /* Endianness doesn't matter in this case because it's
+ a single byte. */
+ fsck_blockmap_set(ip, ip->i_di.di_eattr,
+ _("extended attribute"),
+ sdp->gfs1 ? GFS2_BLKST_DINODE :
+ GFS2_BLKST_USED);
+ log_err( _("The EA was fixed.\n"));
+ error = 0;
+ } else {
+ error = 1;
+ log_err( _("The bad EA was not fixed.\n"));
+ }
+ }
return error;
}
diff --git a/gfs2/fsck/pass1b.c b/gfs2/fsck/pass1b.c
index a9632d8..182c6cb 100644
--- a/gfs2/fsck/pass1b.c
+++ b/gfs2/fsck/pass1b.c
@@ -831,15 +831,22 @@ static int check_eattr_entry_refs(struct gfs2_inode *ip,
return 0;
}
-static int check_eattr_extentry_refs(struct gfs2_inode *ip,
+static int check_eattr_extentry_refs(struct gfs2_inode *ip, int i,
uint64_t *ea_data_ptr,
struct gfs2_buffer_head *leaf_bh,
+ uint32_t tot_ealen,
struct gfs2_ea_header *ea_hdr,
struct gfs2_ea_header *ea_hdr_prev,
void *private)
{
uint64_t block = be64_to_cpu(*ea_data_ptr);
+ /* This is a case where a bad return code may be sent back, and
+ behavior has changed. Before, if add_duplicate_ref returned a
+ non-zero return code, the caller would delete the eattr from
+ the blockmap. In this case, we should be okay because the only
+ error possible is a malloc that fails, in which case we don't
+ want to delete the eattr anyway. */
return add_duplicate_ref(ip, block, ref_as_ea, 1, INODE_VALID);
}