From: Bob Peterson <rpete...@redhat.com> Before this patch, bad extended attributes were not properly removed from a dinode, and blocks were not freed. This patch properly removes them all.
rhbz#872564 --- gfs2/fsck/pass1.c | 12 ++++++++---- gfs2/fsck/pass1c.c | 8 +++++++- gfs2/fsck/pass2.c | 18 ++++++++++-------- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c index d678788..cf2bf99 100644 --- a/gfs2/fsck/pass1.c +++ b/gfs2/fsck/pass1.c @@ -493,6 +493,8 @@ static int remove_inode_eattr(struct gfs2_inode *ip, struct block_count *bc) static int ask_remove_inode_eattr(struct gfs2_inode *ip, struct block_count *bc) { + if (ip->i_di.di_eattr == 0) + return 0; /* eattr was removed prior to this call */ log_err( _("Inode %lld (0x%llx) has unrecoverable Extended Attribute " "errors.\n"), (unsigned long long)ip->i_di.di_num.no_addr, (unsigned long long)ip->i_di.di_num.no_addr); @@ -1080,11 +1082,13 @@ static int handle_ip(struct gfs2_sbd *sdp, struct gfs2_inode *ip) if (fsck_abort) return 0; - error = check_inode_eattr(ip, &pass1_fxns); + if (!error) { + error = check_inode_eattr(ip, &pass1_fxns); - if (error && - !(ip->i_di.di_flags & GFS2_DIF_EA_INDIRECT)) - ask_remove_inode_eattr(ip, &bc); + if (error && + !(ip->i_di.di_flags & GFS2_DIF_EA_INDIRECT)) + ask_remove_inode_eattr(ip, &bc); + } if (ip->i_di.di_blocks != (1 + bc.indir_count + bc.data_count + bc.ea_count)) { diff --git a/gfs2/fsck/pass1c.c b/gfs2/fsck/pass1c.c index 26d47d5..b918de1 100644 --- a/gfs2/fsck/pass1c.c +++ b/gfs2/fsck/pass1c.c @@ -12,6 +12,12 @@ #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, @@ -62,7 +68,7 @@ static int ask_remove_eattr_entry(struct gfs2_sbd *sdp, static int ask_remove_eattr(struct gfs2_inode *ip) { if (query( _("Remove the bad Extended Attribute? (y/n) "))) { - ip->i_di.di_eattr = 0; + check_inode_eattr(ip, &pass1c_fxns_delete); bmodified(ip->i_bh); log_err( _("Bad Extended Attribute removed.\n")); return 1; diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c index 8b38b43..5c27a35 100644 --- a/gfs2/fsck/pass2.c +++ b/gfs2/fsck/pass2.c @@ -20,11 +20,13 @@ #define MAX_FILENAME 256 -struct metawalk_fxns clear_eattrs = { +struct metawalk_fxns pass2_fxns; + +struct metawalk_fxns delete_eattrs = { .check_eattr_indir = delete_eattr_indir, .check_eattr_leaf = delete_eattr_leaf, - .check_eattr_entry = clear_eattr_entry, - .check_eattr_extentry = clear_eattr_extentry, + .check_eattr_entry = delete_eattr_entry, + .check_eattr_extentry = delete_eattr_extentry, }; /* Set children's parent inode in dir_info structure - ext2 does not set @@ -599,7 +601,7 @@ static int basic_dentry_checks(struct gfs2_inode *ip, struct gfs2_dirent *dent, entry_ip = ip; else entry_ip = fsck_load_inode(sdp, entry->no_addr); - check_inode_eattr(entry_ip, &clear_eattrs); + check_inode_eattr(entry_ip, &delete_eattrs); if (entry_ip != ip) fsck_inode_put(&entry_ip); return 1; @@ -683,7 +685,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, entry_ip = ip; else entry_ip = fsck_load_inode(sdp, entry.no_addr); - check_inode_eattr(entry_ip, &clear_eattrs); + check_inode_eattr(entry_ip, &delete_eattrs); if (entry_ip != ip) fsck_inode_put(&entry_ip); goto nuke_dentry; @@ -714,7 +716,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, entry_ip = ip; else entry_ip = fsck_load_inode(sdp, entry.no_addr); - check_inode_eattr(entry_ip, &clear_eattrs); + check_inode_eattr(entry_ip, &delete_eattrs); if (entry_ip != ip) fsck_inode_put(&entry_ip); goto nuke_dentry; @@ -744,7 +746,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, entry_ip = ip; else entry_ip = fsck_load_inode(sdp, entry.no_addr); - check_inode_eattr(entry_ip, &clear_eattrs); + check_inode_eattr(entry_ip, &delete_eattrs); if (entry_ip != ip) fsck_inode_put(&entry_ip); @@ -764,7 +766,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, entry_ip = ip; else entry_ip = fsck_load_inode(sdp, entry.no_addr); - check_inode_eattr(entry_ip, &clear_eattrs); + check_inode_eattr(entry_ip, &delete_eattrs); if (entry_ip != ip) fsck_inode_put(&entry_ip); -- 1.7.11.7