This patch eliminates pass1c and moves its checks to pass1. In
pass1c, it used to delete bad extended attribute blocks, but in
pass1, we have to go about things a little differently. Since
pass1 is prior to resolving duplicate references (pass1b) it
must "undo" the references rather than delete them.
rhbz#1257625
---
gfs2/fsck/Makefile.am | 1 -
gfs2/fsck/main.c | 1 -
gfs2/fsck/pass1.c | 98 ++++++++++-------
gfs2/fsck/pass1c.c | 285 -------------------------------------------------
gfs2/fsck/util.c | 2 -
gfs2/libgfs2/libgfs2.h | 2 -
6 files changed, 62 insertions(+), 327 deletions(-)
delete mode 100644 gfs2/fsck/pass1c.c
diff --git a/gfs2/fsck/Makefile.am b/gfs2/fsck/Makefile.am
index fb93110..73d957e 100644
--- a/gfs2/fsck/Makefile.am
+++ b/gfs2/fsck/Makefile.am
@@ -21,7 +21,6 @@ fsck_gfs2_SOURCES = \
metawalk.c \
pass1b.c \
pass1.c \
- pass1c.c \
pass2.c \
pass3.c \
pass4.c \
diff --git a/gfs2/fsck/main.c b/gfs2/fsck/main.c
index 658cd17..08343ca 100644
--- a/gfs2/fsck/main.c
+++ b/gfs2/fsck/main.c
@@ -237,7 +237,6 @@ struct fsck_pass {
static const struct fsck_pass passes[] = {
{ .name = "pass1", .f = pass1 },
{ .name = "pass1b", .f = pass1b },
- { .name = "pass1c", .f = pass1c },
{ .name = "pass2", .f = pass2 },
{ .name = "pass3", .f = pass3 },
{ .name = "pass4", .f = pass4 },
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index f95e7eb..a892b4b 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -684,8 +684,6 @@ 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);
@@ -693,18 +691,6 @@ static int finish_eattr_indir(struct gfs2_inode *ip, int
leaf_pointers,
"attribute block\n"),
(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. 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 "
@@ -774,7 +760,7 @@ static int check_ealeaf_block(struct gfs2_inode *ip,
uint64_t block, int btype,
}
/* Point of confusion: We've got to set the ea block itself to
GFS2_BLKST_USED here. Elsewhere we mark the inode with
- gfs2_eattr_block meaning it contains an eattr for pass1c. */
+ gfs2_eattr_block meaning it contains an eattr. */
fsck_blockmap_set(ip, block, _("Extended Attribute"),
sdp->gfs1 ? GFS2_BLKST_DINODE : GFS2_BLKST_USED);
bc->ea_count++;
@@ -830,24 +816,7 @@ 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.
- * Clarification: If we're here we're checking a leaf block, and the
- * source dinode needs to be marked as having extended attributes.
- * That instructs pass1c to check the contents of the ea blocks. */
- log_debug( _("Setting inode %lld (0x%llx) as having eattr "
- "block(s) attached.\n"),
- (unsigned long long)ip->i_di.di_num.no_addr,
- (unsigned long long)ip->i_di.di_num.no_addr);
- 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 (!valid_block(sdp, block)) {
log_warn( _("Inode #%llu (0x%llx): Extended Attribute leaf "
"block #%llu (0x%llx) is invalid or out of "
@@ -863,6 +832,41 @@ static int check_eattr_leaf(struct gfs2_inode *ip,
uint64_t block,
return check_ealeaf_block(ip, block, GFS2_METATYPE_EA, bh, private);
}
+static int ask_remove_eattr_entry(struct gfs2_sbd *sdp,
+ struct gfs2_buffer_head *leaf_bh,
+ struct gfs2_ea_header *curr,
+ struct gfs2_ea_header *prev,
+ int fix_curr, int fix_curr_len)
+{
+ if (!query( _("Remove the bad Extended Attribute entry? (y/n) "))) {
+ log_err( _("Bad Extended Attribute not removed.\n"));
+ return 0;
+ }
+ if (fix_curr)
+ curr->ea_flags |= GFS2_EAFLAG_LAST;
+ if (fix_curr_len) {
+ uint32_t max_size = sdp->sd_sb.sb_bsize;
+ uint32_t offset = (uint32_t)(((unsigned long)curr) -
+ ((unsigned long)leaf_bh->b_data));
+ curr->ea_rec_len = cpu_to_be32(max_size - offset);
+ }
+ if (!prev)
+ curr->ea_type = GFS2_EATYPE_UNUSED;
+ else {
+ uint32_t tmp32 = be32_to_cpu(curr->ea_rec_len) +
+ be32_to_cpu(prev->ea_rec_len);
+ prev->ea_rec_len = cpu_to_be32(tmp32);
+ if (curr->ea_flags & GFS2_EAFLAG_LAST)
+ prev->ea_flags |= GFS2_EAFLAG_LAST;
+ }
+ log_err( _("Bad Extended Attribute at block #%llu"
+ " (0x%llx) removed.\n"),
+ (unsigned long long)leaf_bh->b_blocknr,
+ (unsigned long long)leaf_bh->b_blocknr);
+ bmodified(leaf_bh);
+ return 1;
+}
+
static int check_eattr_entries(struct gfs2_inode *ip,
struct gfs2_buffer_head *leaf_bh,
struct gfs2_ea_header *ea_hdr,
@@ -871,12 +875,32 @@ static int check_eattr_entries(struct gfs2_inode *ip,
{
struct gfs2_sbd *sdp = ip->i_sbd;
char ea_name[256];
+ uint32_t offset = (uint32_t)(((unsigned long)ea_hdr) -
+ ((unsigned long)leaf_bh->b_data));
+ uint32_t max_size = sdp->sd_sb.sb_bsize;
uint32_t avail_size;
int max_ptrs;
if (!ea_hdr->ea_name_len){
- /* Skip this entry for now */
- return 1;
+ log_err( _("EA has name length of zero\n"));
+ return ask_remove_eattr_entry(sdp, leaf_bh, ea_hdr,
+ ea_hdr_prev, 1, 1);
+ }
+ if (offset + be32_to_cpu(ea_hdr->ea_rec_len) > max_size){
+ log_err( _("EA rec length too long\n"));
+ return ask_remove_eattr_entry(sdp, leaf_bh, ea_hdr,
+ ea_hdr_prev, 1, 1);
+ }
+ if (offset + be32_to_cpu(ea_hdr->ea_rec_len) == max_size &&
+ (ea_hdr->ea_flags & GFS2_EAFLAG_LAST) == 0){
+ log_err( _("last EA has no last entry flag\n"));
+ return ask_remove_eattr_entry(sdp, leaf_bh, ea_hdr,
+ ea_hdr_prev, 0, 0);
+ }
+ if (!ea_hdr->ea_name_len){
+ log_err( _("EA has name length of zero\n"));
+ return ask_remove_eattr_entry(sdp, leaf_bh, ea_hdr,
+ ea_hdr_prev, 0, 0);
}
memset(ea_name, 0, sizeof(ea_name));
@@ -888,7 +912,8 @@ static int check_eattr_entries(struct gfs2_inode *ip,
/* Skip invalid entry */
log_err(_("EA (%s) type is invalid (%d > %d).\n"),
ea_name, ea_hdr->ea_type, GFS2_EATYPE_LAST);
- return 1;
+ return ask_remove_eattr_entry(sdp, leaf_bh, ea_hdr,
+ ea_hdr_prev, 0, 0);
}
if (!ea_hdr->ea_num_ptrs)
@@ -902,7 +927,8 @@ static int check_eattr_entries(struct gfs2_inode *ip,
ea_name);
log_err(_(" Required: %d\n Reported: %d\n"),
max_ptrs, ea_hdr->ea_num_ptrs);
- return 1;
+ return ask_remove_eattr_entry(sdp, leaf_bh, ea_hdr,
+ ea_hdr_prev, 0, 0);
} else {
log_debug( _(" Pointers Required: %d\n Pointers Reported:
%d\n"),
max_ptrs, ea_hdr->ea_num_ptrs);
diff --git a/gfs2/fsck/pass1c.c b/gfs2/fsck/pass1c.c
deleted file mode 100644
index aa905da..0000000
--- a/gfs2/fsck/pass1c.c
+++ /dev/null
@@ -1,285 +0,0 @@
-#include "clusterautoconfig.h"
-
-#include <inttypes.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <libintl.h>
-#define _(String) gettext(String)
-
-#include <logging.h>
-#include "libgfs2.h"
-#include "fsck.h"
-#include "util.h"
-#include "metawalk.h"
-
-struct metawalk_fxns pass1c_fxns_delete = {
- .private = NULL,
- .check_eattr_indir = delete_eattr_indir,
- .check_eattr_leaf = delete_eattr_leaf,
-};
-
-static int remove_eattr_entry(struct gfs2_sbd *sdp,
- struct gfs2_buffer_head *leaf_bh,
- struct gfs2_ea_header *curr,
- struct gfs2_ea_header *prev)
-{
- if (!prev)
- curr->ea_type = GFS2_EATYPE_UNUSED;
- else {
- uint32_t tmp32 = be32_to_cpu(curr->ea_rec_len) +
- be32_to_cpu(prev->ea_rec_len);
- prev->ea_rec_len = cpu_to_be32(tmp32);
- if (curr->ea_flags & GFS2_EAFLAG_LAST)
- prev->ea_flags |= GFS2_EAFLAG_LAST;
- }
- log_err( _("Bad Extended Attribute at block #%llu"
- " (0x%llx) removed.\n"),
- (unsigned long long)leaf_bh->b_blocknr,
- (unsigned long long)leaf_bh->b_blocknr);
- bmodified(leaf_bh);
- return 0;
-}
-
-static int ask_remove_eattr_entry(struct gfs2_sbd *sdp,
- struct gfs2_buffer_head *leaf_bh,
- struct gfs2_ea_header *curr,
- struct gfs2_ea_header *prev,
- int fix_curr, int fix_curr_len)
-{
- if (query( _("Remove the bad Extended Attribute entry? (y/n) "))) {
- if (fix_curr)
- curr->ea_flags |= GFS2_EAFLAG_LAST;
- if (fix_curr_len) {
- uint32_t max_size = sdp->sd_sb.sb_bsize;
- uint32_t offset = (uint32_t)(((unsigned long)curr) -
- ((unsigned long)leaf_bh->b_data));
- curr->ea_rec_len = cpu_to_be32(max_size - offset);
- }
- if (remove_eattr_entry(sdp, leaf_bh, curr, prev)) {
- stack;
- return -1;
- }
- } else {
- log_err( _("Bad Extended Attribute not removed.\n"));
- }
- return 1;
-}
-
-static int ask_remove_eattr(struct gfs2_inode *ip)
-{
- if (query( _("Remove the bad Extended Attribute? (y/n) "))) {
- check_inode_eattr(ip, &pass1c_fxns_delete);
- bmodified(ip->i_bh);
- log_err( _("Bad Extended Attribute removed.\n"));
- return 1;
- }
- log_err( _("Bad Extended Attribute not removed.\n"));
- return 0;
-}
-
-static int check_eattr_indir(struct gfs2_inode *ip, uint64_t block,
- uint64_t parent, struct gfs2_buffer_head **bh,
- void *private)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
- uint8_t q;
- struct gfs2_buffer_head *indir_bh = NULL;
-
- if (!valid_block(sdp, block)) {
- log_err( _("Extended attributes indirect block #%llu"
- " (0x%llx) for inode #%llu"
- " (0x%llx) is invalid...removing\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 != (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"),
- (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);
- }
- else
- indir_bh = bread(sdp, block);
-
- *bh = indir_bh;
- return 0;
-}
-
-static int check_eattr_leaf(struct gfs2_inode *ip, uint64_t block,
- uint64_t parent, struct gfs2_buffer_head **bh,
- void *private)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
- uint8_t q;
-
- if (!valid_block(sdp, block)) {
- 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 != (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);
- }
- else
- *bh = bread(sdp, block);
-
- return 0;
-}
-
-static int check_eattr_entry(struct gfs2_inode *ip,
- struct gfs2_buffer_head *leaf_bh,
- struct gfs2_ea_header *ea_hdr,
- struct gfs2_ea_header *ea_hdr_prev,
- void *private)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
- char ea_name[256];
- uint32_t offset = (uint32_t)(((unsigned long)ea_hdr) -
- ((unsigned long)leaf_bh->b_data));
- uint32_t max_size = sdp->sd_sb.sb_bsize;
-
- if (!ea_hdr->ea_name_len){
- log_err( _("EA has name length of zero\n"));
- return ask_remove_eattr_entry(sdp, leaf_bh, ea_hdr,
- ea_hdr_prev, 1, 1);
- }
- if (offset + be32_to_cpu(ea_hdr->ea_rec_len) > max_size){
- log_err( _("EA rec length too long\n"));
- return ask_remove_eattr_entry(sdp, leaf_bh, ea_hdr,
- ea_hdr_prev, 1, 1);
- }
- if (offset + be32_to_cpu(ea_hdr->ea_rec_len) == max_size &&
- (ea_hdr->ea_flags & GFS2_EAFLAG_LAST) == 0){
- log_err( _("last EA has no last entry flag\n"));
- return ask_remove_eattr_entry(sdp, leaf_bh, ea_hdr,
- ea_hdr_prev, 0, 0);
- }
- if (!ea_hdr->ea_name_len){
- log_err( _("EA has name length of zero\n"));
- return ask_remove_eattr_entry(sdp, leaf_bh, ea_hdr,
- ea_hdr_prev, 0, 0);
- }
-
- memset(ea_name, 0, sizeof(ea_name));
- strncpy(ea_name, (char *)ea_hdr + sizeof(struct gfs2_ea_header),
- ea_hdr->ea_name_len);
-
- if (!GFS2_EATYPE_VALID(ea_hdr->ea_type) &&
- ((ea_hdr_prev) || (!ea_hdr_prev && ea_hdr->ea_type))){
- log_err( _("EA (%s) type is invalid (%d > %d).\n"),
- ea_name, ea_hdr->ea_type, GFS2_EATYPE_LAST);
- return ask_remove_eattr_entry(sdp, leaf_bh, ea_hdr,
- ea_hdr_prev, 0, 0);
- }
-
- if (ea_hdr->ea_num_ptrs){
- uint32_t avail_size;
- int max_ptrs;
-
- avail_size = sdp->sd_sb.sb_bsize - sizeof(struct
gfs2_meta_header);
- max_ptrs =
(be32_to_cpu(ea_hdr->ea_data_len)+avail_size-1)/avail_size;
-
- if (max_ptrs > ea_hdr->ea_num_ptrs){
- log_err( _("EA (%s) has incorrect number of
pointers.\n"), ea_name);
- log_err( _(" Required: %d\n Reported: %d\n"),
- max_ptrs, ea_hdr->ea_num_ptrs);
- return ask_remove_eattr_entry(sdp, leaf_bh, ea_hdr,
- ea_hdr_prev, 0, 0);
- } else {
- log_debug( _(" Pointers Required: %d\n Pointers
Reported: %d\n"),
- max_ptrs, ea_hdr->ea_num_ptrs);
- }
- }
- return 0;
-}
-
-static int check_eattr_extentry(struct gfs2_inode *ip, uint64_t *ea_ptr,
- struct gfs2_buffer_head *leaf_bh,
- struct gfs2_ea_header *ea_hdr,
- struct gfs2_ea_header *ea_hdr_prev, void *private)
-{
- uint8_t q;
- struct gfs2_sbd *sdp = ip->i_sbd;
-
- q = block_type(be64_to_cpu(*ea_ptr));
- 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;
- }
- return 1;
- }
- return 0;
-}
-
-/* Go over all inodes with extended attributes and verify the EAs are
- * valid */
-int pass1c(struct gfs2_sbd *sdp)
-{
- uint64_t block_no = 0;
- struct gfs2_buffer_head *bh;
- struct gfs2_inode *ip = NULL;
- struct metawalk_fxns pass1c_fxns = { 0 };
- int error = 0;
- osi_list_t *tmp, *x;
- struct special_blocks *ea_block;
-
- pass1c_fxns.check_eattr_indir = &check_eattr_indir;
- pass1c_fxns.check_eattr_leaf = &check_eattr_leaf;
- pass1c_fxns.check_eattr_entry = &check_eattr_entry;
- pass1c_fxns.check_eattr_extentry = &check_eattr_extentry;
- pass1c_fxns.private = NULL;
-
- log_info( _("Looking for inodes containing ea blocks...\n"));
- osi_list_foreach_safe(tmp, &sdp->eattr_blocks.list, x) {
- ea_block = osi_list_entry(tmp, struct special_blocks, list);
- block_no = ea_block->block;
- warm_fuzzy_stuff(block_no);
-
- if (skip_this_pass || fsck_abort) /* if asked to skip the rest
*/
- return FSCK_OK;
- bh = bread(sdp, block_no);
- if (!gfs2_check_meta(bh, GFS2_METATYPE_DI)) { /* if a dinode */
- log_info( _("EA in inode %llu (0x%llx)\n"),
- (unsigned long long)block_no,
- (unsigned long long)block_no);
- gfs2_special_clear(&sdp->eattr_blocks, block_no);
- ip = fsck_inode_get(sdp, bh);
- ip->bh_owned = 1;
-
- log_debug( _("Found eattr at %llu (0x%llx)\n"),
- (unsigned long long)ip->i_di.di_eattr,
- (unsigned long long)ip->i_di.di_eattr);
- /* FIXME: Handle walking the eattr here */
- error = check_inode_eattr(ip, &pass1c_fxns);
- if (error < 0) {
- stack;
- brelse(bh);
- return FSCK_ERROR;
- }
-
- fsck_inode_put(&ip); /* dinode_out, brelse, free */
- } else {
- brelse(bh);
- }
- }
- return FSCK_OK;
-}
diff --git a/gfs2/fsck/util.c b/gfs2/fsck/util.c
index b22abc6..2745692 100644
--- a/gfs2/fsck/util.c
+++ b/gfs2/fsck/util.c
@@ -556,7 +556,6 @@ struct gfs2_bmap *gfs2_bmap_create(struct gfs2_sbd *sdp,
uint64_t size,
free(il);
il = NULL;
}
- osi_list_init(&sdp->eattr_blocks.list);
return il;
}
@@ -584,7 +583,6 @@ void *gfs2_bmap_destroy(struct gfs2_sbd *sdp, struct
gfs2_bmap *il)
free(il);
il = NULL;
}
- gfs2_special_free(&sdp->eattr_blocks);
return il;
}
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index ccae721..12d57c7 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -304,8 +304,6 @@ struct gfs2_sbd {
struct gfs2_inode *master_dir;
struct master_dir md;
- struct special_blocks eattr_blocks;
-
uint64_t rg_one_length;
uint64_t rg_length;
int gfs1;
--
2.4.3