From mboxrd@z Thu Jan 1 00:00:00 1970 From: Andrew Price Date: Mon, 9 May 2016 15:55:31 +0100 Subject: [Cluster-devel] [fsck.gfs2 v2 PATCH 12/40] fsck.gfs2: Separate out functions that may only be done after pass1 In-Reply-To: References: Message-ID: <5730A4E3.2030305@redhat.com> List-Id: To: cluster-devel.redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit On 06/05/16 18:39, Bob Peterson wrote: > This patch adds a new header file and source file which has the > purpose of separating out the functions that may only be called > after pass1 from the functions that pass1 may call. This is to > ensure that there will never be inconsistencies between blockmap > (which pass1 uses) and bitmap (which subsequent passes use). > > Signed-off-by: Bob Peterson > --- > gfs2/fsck/Makefile.am | 1 + > gfs2/fsck/afterpass1_common.c | 272 ++++++++++++++++++++++++++++++++++++++++++ > gfs2/fsck/afterpass1_common.h | 31 +++++ > gfs2/fsck/metawalk.c | 272 +----------------------------------------- > gfs2/fsck/metawalk.h | 32 +---- > gfs2/fsck/pass1.c | 22 ++++ > gfs2/fsck/pass1b.c | 1 + > gfs2/fsck/pass2.c | 1 + > gfs2/fsck/pass3.c | 1 + > gfs2/fsck/pass4.c | 1 + > 10 files changed, 335 insertions(+), 299 deletions(-) > create mode 100644 gfs2/fsck/afterpass1_common.c > create mode 100644 gfs2/fsck/afterpass1_common.h The .h file should be added to noinst_HEADERS in gfs2/fsck/Makefile.am Andy > diff --git a/gfs2/fsck/Makefile.am b/gfs2/fsck/Makefile.am > index 73d957e..ecd05d8 100644 > --- a/gfs2/fsck/Makefile.am > +++ b/gfs2/fsck/Makefile.am > @@ -19,6 +19,7 @@ fsck_gfs2_SOURCES = \ > lost_n_found.c \ > main.c \ > metawalk.c \ > + afterpass1_common.c \ > pass1b.c \ > pass1.c \ > pass2.c \ > diff --git a/gfs2/fsck/afterpass1_common.c b/gfs2/fsck/afterpass1_common.c > new file mode 100644 > index 0000000..36646f8 > --- /dev/null > +++ b/gfs2/fsck/afterpass1_common.c > @@ -0,0 +1,272 @@ > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#define _(String) gettext(String) > + > +#include > +#include "libgfs2.h" > +#include "fsck.h" > +#include "afterpass1_common.h" > +#include "metawalk.h" > +#include "util.h" > + > +/** > + * find_remove_dup - find out if this is a duplicate ref. If so, remove it. > + * > + * Returns: 1 if there are any remaining references to this block, else 0. > + */ > +int find_remove_dup(struct gfs2_inode *ip, uint64_t block, const char *btype) > +{ > + struct duptree *dt; > + struct inode_with_dups *id; > + > + dt = dupfind(block); > + if (!dt) > + return 0; > + > + /* remove the inode reference id structure for this reference. */ > + id = find_dup_ref_inode(dt, ip); > + if (!id) > + goto more_refs; > + > + dup_listent_delete(dt, id); > + if (dt->refs == 0) { > + log_info( _("This was the last reference: it's no longer a " > + "duplicate.\n")); > + dup_delete(dt); /* not duplicate now */ > + return 0; > + } > +more_refs: > + log_info( _("%d block reference(s) remain.\n"), dt->refs); > + return 1; /* references still exist so do not free the block. */ > +} > + > +/** > + * delete_block_if_notdup - delete blocks associated with an inode > + * > + * Ignore blocks that are already marked free. > + * If it has been identified as duplicate, remove the duplicate reference. > + * If all duplicate references have been removed, delete the block. > + */ > +static int delete_block_if_notdup(struct gfs2_inode *ip, uint64_t block, > + struct gfs2_buffer_head **bh, > + const char *btype, int *was_duplicate, > + void *private) > +{ > + int q; > + > + if (!valid_block(ip->i_sbd, block)) > + return meta_error; > + > + q = bitmap_type(ip->i_sbd, block); > + 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, > + (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 meta_is_good; > + } > + if (find_remove_dup(ip, block, btype)) { /* a dup */ > + if (was_duplicate) > + *was_duplicate = 1; > + log_err( _("Not clearing duplicate reference in inode " > + "at block #%llu (0x%llx) to block #%llu (0x%llx) " > + "because it's referenced by another inode.\n"), > + (unsigned long long)ip->i_di.di_num.no_addr, > + (unsigned long long)ip->i_di.di_num.no_addr, > + (unsigned long long)block, (unsigned long long)block); > + } else { > + check_n_fix_bitmap(ip->i_sbd, block, 0, GFS2_BLKST_FREE); > + } > + return meta_is_good; > +} > + > +static int remove_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, > + struct gfs2_dirent *prev_de, > + struct gfs2_buffer_head *bh, > + char *filename, uint32_t *count, int *lindex, > + void *private) > +{ > + /* the metawalk_fxn's private field must be set to the dentry > + * block we want to clear */ > + uint64_t *dentryblock = (uint64_t *) private; > + struct gfs2_dirent dentry, *de; > + > + memset(&dentry, 0, sizeof(struct gfs2_dirent)); > + gfs2_dirent_in(&dentry, (char *)dent); > + de = &dentry; > + > + if (de->de_inum.no_addr == *dentryblock) > + dirent2_del(ip, bh, prev_de, dent); > + else > + (*count)++; > + > + return 0; > + > +} > + > +int remove_dentry_from_dir(struct gfs2_sbd *sdp, uint64_t dir, > + uint64_t dentryblock) > +{ > + struct metawalk_fxns remove_dentry_fxns = {0}; > + struct gfs2_inode *ip; > + int q; > + int error; > + > + log_debug( _("Removing dentry %llu (0x%llx) from directory %llu" > + " (0x%llx)\n"), (unsigned long long)dentryblock, > + (unsigned long long)dentryblock, > + (unsigned long long)dir, (unsigned long long)dir); > + if (!valid_block(sdp, dir)) { > + log_err( _("Parent directory is invalid\n")); > + return 1; > + } > + remove_dentry_fxns.private = &dentryblock; > + remove_dentry_fxns.check_dentry = remove_dentry; > + > + q = bitmap_type(sdp, dir); > + if (q != GFS2_BLKST_DINODE) { > + log_info( _("Parent block is not an inode...ignoring\n")); > + return 1; > + } > + > + ip = fsck_load_inode(sdp, dir); > + if (ip == NULL) { > + stack; > + return -1; > + } > + /* Need to run check_dir with a private var of dentryblock, > + * and fxns that remove that dentry if found */ > + error = check_dir(sdp, ip, &remove_dentry_fxns); > + fsck_inode_put(&ip); > + return error; > +} > + > +int delete_metadata(struct gfs2_inode *ip, uint64_t block, > + struct gfs2_buffer_head **bh, int h, int *is_valid, > + int *was_duplicate, void *private) > +{ > + *is_valid = 1; > + *was_duplicate = 0; > + return delete_block_if_notdup(ip, block, bh, _("metadata"), > + was_duplicate, private); > +} > + > +int delete_leaf(struct gfs2_inode *ip, uint64_t block, void *private) > +{ > + return delete_block_if_notdup(ip, block, NULL, _("leaf"), NULL, > + private); > +} > + > +int delete_data(struct gfs2_inode *ip, uint64_t metablock, > + uint64_t block, void *private, struct gfs2_buffer_head *bh, > + uint64_t *ptr) > +{ > + return delete_block_if_notdup(ip, block, NULL, _("data"), NULL, > + private); > +} > + > +static int del_eattr_generic(struct gfs2_inode *ip, uint64_t block, > + uint64_t parent, struct gfs2_buffer_head **bh, > + void *private, const char *eatype) > +{ > + int ret = 0; > + int was_free = 0; > + int q; > + > + if (valid_block(ip->i_sbd, block)) { > + q = bitmap_type(ip->i_sbd, block); > + if (q == GFS2_BLKST_FREE) > + was_free = 1; > + ret = delete_block_if_notdup(ip, block, NULL, eatype, > + NULL, private); > + if (!ret) { > + *bh = bread(ip->i_sbd, block); > + if (!was_free) > + ip->i_di.di_blocks--; > + bmodified(ip->i_bh); > + } > + } > + /* Even if it's a duplicate reference, we want to eliminate the > + reference itself, and adjust di_blocks accordingly. */ > + if (ip->i_di.di_eattr) { > + if (block == ip->i_di.di_eattr) > + ip->i_di.di_eattr = 0; > + bmodified(ip->i_bh); > + } > + return ret; > +} > + > +int delete_eattr_indir(struct gfs2_inode *ip, uint64_t block, uint64_t parent, > + struct gfs2_buffer_head **bh, void *private) > +{ > + return del_eattr_generic(ip, block, parent, bh, private, > + _("extended attribute")); > +} > + > +int delete_eattr_leaf(struct gfs2_inode *ip, uint64_t block, uint64_t parent, > + struct gfs2_buffer_head **bh, void *private) > +{ > + return del_eattr_generic(ip, block, parent, bh, private, > + _("indirect extended attribute")); > +} > + > +int delete_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 avail_size; > + int max_ptrs; > + > + if (!ea_hdr->ea_name_len){ > + /* Skip this entry for now */ > + return 1; > + } > + > + 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))){ > + /* Skip invalid entry */ > + return 1; > + } > + > + if (!ea_hdr->ea_num_ptrs) > + return 0; > + > + 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) > + return 1; > + > + log_debug( _(" Pointers Required: %d\n Pointers Reported: %d\n"), > + max_ptrs, ea_hdr->ea_num_ptrs); > + > + return 0; > +} > + > +int delete_eattr_extentry(struct gfs2_inode *ip, uint64_t *ea_data_ptr, > + struct gfs2_buffer_head *leaf_bh, > + struct gfs2_ea_header *ea_hdr, > + struct gfs2_ea_header *ea_hdr_prev, void *private) > +{ > + uint64_t block = be64_to_cpu(*ea_data_ptr); > + > + return delete_block_if_notdup(ip, block, NULL, _("extended attribute"), > + NULL, private); > +} > diff --git a/gfs2/fsck/afterpass1_common.h b/gfs2/fsck/afterpass1_common.h > new file mode 100644 > index 0000000..2a422c7 > --- /dev/null > +++ b/gfs2/fsck/afterpass1_common.h > @@ -0,0 +1,31 @@ > +#ifndef _AFTERPASS1_H > +#define _AFTERPASS1_H > + > +#include "util.h" > + > +extern int delete_metadata(struct gfs2_inode *ip, uint64_t block, > + struct gfs2_buffer_head **bh, int h, int *is_valid, > + int *was_duplicate, void *private); > +extern int delete_leaf(struct gfs2_inode *ip, uint64_t block, void *private); > +extern int delete_data(struct gfs2_inode *ip, uint64_t metablock, > + uint64_t block, void *private, > + struct gfs2_buffer_head *bh, uint64_t *ptr); > +extern int delete_eattr_indir(struct gfs2_inode *ip, uint64_t block, uint64_t parent, > + struct gfs2_buffer_head **bh, void *private); > +extern int delete_eattr_leaf(struct gfs2_inode *ip, uint64_t block, uint64_t parent, > + struct gfs2_buffer_head **bh, void *private); > +extern int delete_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); > +extern int delete_eattr_extentry(struct gfs2_inode *ip, uint64_t *ea_data_ptr, > + struct gfs2_buffer_head *leaf_bh, > + struct gfs2_ea_header *ea_hdr, > + struct gfs2_ea_header *ea_hdr_prev, > + void *private); > +extern int find_remove_dup(struct gfs2_inode *ip, uint64_t block, > + const char *btype); > +extern int remove_dentry_from_dir(struct gfs2_sbd *sdp, uint64_t dir, > + uint64_t dentryblock); > +#endif > diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c > index 7a77dc9..1f2bc10 100644 > --- a/gfs2/fsck/metawalk.c > +++ b/gfs2/fsck/metawalk.c > @@ -989,93 +989,6 @@ static int check_leaf_eattr(struct gfs2_inode *ip, uint64_t block, > } > > /** > - * delete_block - delete a block associated with an inode > - */ > -int delete_block(struct gfs2_inode *ip, uint64_t block, > - struct gfs2_buffer_head **bh, const char *btype, > - void *private) > -{ > - if (valid_block(ip->i_sbd, block)) { > - fsck_blockmap_set(ip, block, btype, GFS2_BLKST_FREE); > - return 0; > - } > - return -1; > -} > - > -/** > - * find_remove_dup - find out if this is a duplicate ref. If so, remove it. > - * > - * Returns: 1 if there are any remaining references to this block, else 0. > - */ > -int find_remove_dup(struct gfs2_inode *ip, uint64_t block, const char *btype) > -{ > - struct duptree *dt; > - struct inode_with_dups *id; > - > - dt = dupfind(block); > - if (!dt) > - return 0; > - > - /* remove the inode reference id structure for this reference. */ > - id = find_dup_ref_inode(dt, ip); > - if (!id) > - goto more_refs; > - > - dup_listent_delete(dt, id); > - if (dt->refs == 0) { > - log_info( _("This was the last reference: it's no longer a " > - "duplicate.\n")); > - dup_delete(dt); /* not duplicate now */ > - return 0; > - } > -more_refs: > - log_info( _("%d block reference(s) remain.\n"), dt->refs); > - return 1; /* references still exist so do not free the block. */ > -} > - > -/** > - * delete_block_if_notdup - delete blocks associated with an inode > - * > - * Ignore blocks that are already marked free. > - * If it has been identified as duplicate, remove the duplicate reference. > - * If all duplicate references have been removed, delete the block. > - */ > -static int delete_block_if_notdup(struct gfs2_inode *ip, uint64_t block, > - struct gfs2_buffer_head **bh, > - const char *btype, int *was_duplicate, > - void *private) > -{ > - int q; > - > - if (!valid_block(ip->i_sbd, block)) > - return meta_error; > - > - q = bitmap_type(ip->i_sbd, block); > - 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, > - (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 meta_is_good; > - } > - if (find_remove_dup(ip, block, btype)) { /* a dup */ > - if (was_duplicate) > - *was_duplicate = 1; > - log_err( _("Not clearing duplicate reference in inode " > - "at block #%llu (0x%llx) to block #%llu (0x%llx) " > - "because it's referenced by another inode.\n"), > - (unsigned long long)ip->i_di.di_num.no_addr, > - (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_BLKST_FREE); > - } > - return meta_is_good; > -} > - > -/** > * check_indirect_eattr > * @ip: the inode the eattr comes from > * @indirect_block > @@ -1159,9 +1072,9 @@ static int check_indirect_eattr(struct gfs2_inode *ip, uint64_t indirect, > leaf_pointer_errors, > pass->private); > } > - if (leaf_pointer_errors && > + if (pass->delete_block && leaf_pointer_errors && > leaf_pointer_errors == leaf_pointers) { > - delete_block(ip, indirect, NULL, "leaf", NULL); > + pass->delete_block(ip, indirect, NULL, "leaf", NULL); > error = 1; > } > } > @@ -1729,184 +1642,3 @@ int check_dir(struct gfs2_sbd *sdp, struct gfs2_inode *ip, struct metawalk_fxns > > return error; > } > - > -static int remove_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, > - struct gfs2_dirent *prev_de, > - struct gfs2_buffer_head *bh, > - char *filename, uint32_t *count, int *lindex, > - void *private) > -{ > - /* the metawalk_fxn's private field must be set to the dentry > - * block we want to clear */ > - uint64_t *dentryblock = (uint64_t *) private; > - struct gfs2_dirent dentry, *de; > - > - memset(&dentry, 0, sizeof(struct gfs2_dirent)); > - gfs2_dirent_in(&dentry, (char *)dent); > - de = &dentry; > - > - if (de->de_inum.no_addr == *dentryblock) > - dirent2_del(ip, bh, prev_de, dent); > - else > - (*count)++; > - > - return 0; > - > -} > - > -int remove_dentry_from_dir(struct gfs2_sbd *sdp, uint64_t dir, > - uint64_t dentryblock) > -{ > - struct metawalk_fxns remove_dentry_fxns = {0}; > - struct gfs2_inode *ip; > - int q; > - int error; > - > - log_debug( _("Removing dentry %llu (0x%llx) from directory %llu" > - " (0x%llx)\n"), (unsigned long long)dentryblock, > - (unsigned long long)dentryblock, > - (unsigned long long)dir, (unsigned long long)dir); > - if (!valid_block(sdp, dir)) { > - log_err( _("Parent directory is invalid\n")); > - return 1; > - } > - remove_dentry_fxns.private = &dentryblock; > - remove_dentry_fxns.check_dentry = remove_dentry; > - > - q = bitmap_type(sdp, dir); > - if (q != GFS2_BLKST_DINODE) { > - log_info( _("Parent block is not an inode...ignoring\n")); > - return 1; > - } > - > - ip = fsck_load_inode(sdp, dir); > - if (ip == NULL) { > - stack; > - return -1; > - } > - /* Need to run check_dir with a private var of dentryblock, > - * and fxns that remove that dentry if found */ > - error = check_dir(sdp, ip, &remove_dentry_fxns); > - fsck_inode_put(&ip); > - return error; > -} > - > -int delete_metadata(struct gfs2_inode *ip, uint64_t block, > - struct gfs2_buffer_head **bh, int h, int *is_valid, > - int *was_duplicate, void *private) > -{ > - *is_valid = 1; > - *was_duplicate = 0; > - return delete_block_if_notdup(ip, block, bh, _("metadata"), > - was_duplicate, private); > -} > - > -int delete_leaf(struct gfs2_inode *ip, uint64_t block, void *private) > -{ > - return delete_block_if_notdup(ip, block, NULL, _("leaf"), NULL, > - private); > -} > - > -int delete_data(struct gfs2_inode *ip, uint64_t metablock, > - uint64_t block, void *private, struct gfs2_buffer_head *bh, > - uint64_t *ptr) > -{ > - return delete_block_if_notdup(ip, block, NULL, _("data"), NULL, > - private); > -} > - > -static int del_eattr_generic(struct gfs2_inode *ip, uint64_t block, > - uint64_t parent, struct gfs2_buffer_head **bh, > - void *private, const char *eatype) > -{ > - int ret = 0; > - int was_free = 0; > - int q; > - > - if (valid_block(ip->i_sbd, block)) { > - q = bitmap_type(ip->i_sbd, block); > - if (q == GFS2_BLKST_FREE) > - was_free = 1; > - ret = delete_block_if_notdup(ip, block, NULL, eatype, > - NULL, private); > - if (!ret) { > - *bh = bread(ip->i_sbd, block); > - if (!was_free) > - ip->i_di.di_blocks--; > - bmodified(ip->i_bh); > - } > - } > - /* Even if it's a duplicate reference, we want to eliminate the > - reference itself, and adjust di_blocks accordingly. */ > - if (ip->i_di.di_eattr) { > - if (block == ip->i_di.di_eattr) > - ip->i_di.di_eattr = 0; > - bmodified(ip->i_bh); > - } > - return ret; > -} > - > -int delete_eattr_indir(struct gfs2_inode *ip, uint64_t block, uint64_t parent, > - struct gfs2_buffer_head **bh, void *private) > -{ > - return del_eattr_generic(ip, block, parent, bh, private, > - _("extended attribute")); > -} > - > -int delete_eattr_leaf(struct gfs2_inode *ip, uint64_t block, uint64_t parent, > - struct gfs2_buffer_head **bh, void *private) > -{ > - return del_eattr_generic(ip, block, parent, bh, private, > - _("indirect extended attribute")); > -} > - > -int delete_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 avail_size; > - int max_ptrs; > - > - if (!ea_hdr->ea_name_len){ > - /* Skip this entry for now */ > - return 1; > - } > - > - 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))){ > - /* Skip invalid entry */ > - return 1; > - } > - > - if (!ea_hdr->ea_num_ptrs) > - return 0; > - > - 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) > - return 1; > - > - log_debug( _(" Pointers Required: %d\n Pointers Reported: %d\n"), > - max_ptrs, ea_hdr->ea_num_ptrs); > - > - return 0; > -} > - > -int delete_eattr_extentry(struct gfs2_inode *ip, uint64_t *ea_data_ptr, > - struct gfs2_buffer_head *leaf_bh, > - struct gfs2_ea_header *ea_hdr, > - struct gfs2_ea_header *ea_hdr_prev, void *private) > -{ > - uint64_t block = be64_to_cpu(*ea_data_ptr); > - > - return delete_block_if_notdup(ip, block, NULL, _("extended attribute"), > - NULL, private); > -} > diff --git a/gfs2/fsck/metawalk.h b/gfs2/fsck/metawalk.h > index d505945..d2f0d97 100644 > --- a/gfs2/fsck/metawalk.h > +++ b/gfs2/fsck/metawalk.h > @@ -19,33 +19,6 @@ extern int check_linear_dir(struct gfs2_inode *ip, struct gfs2_buffer_head *bh, > extern int check_leaf(struct gfs2_inode *ip, int lindex, > struct metawalk_fxns *pass, uint64_t *leaf_no, > struct gfs2_leaf *leaf, int *ref_count); > -extern int remove_dentry_from_dir(struct gfs2_sbd *sdp, uint64_t dir, > - uint64_t dentryblock); > -extern int delete_block(struct gfs2_inode *ip, uint64_t block, > - struct gfs2_buffer_head **bh, const char *btype, > - void *private); > -extern int delete_metadata(struct gfs2_inode *ip, uint64_t block, > - struct gfs2_buffer_head **bh, int h, int *is_valid, > - int *was_duplicate, void *private); > -extern int delete_leaf(struct gfs2_inode *ip, uint64_t block, void *private); > -extern int delete_data(struct gfs2_inode *ip, uint64_t metablock, > - uint64_t block, void *private, > - struct gfs2_buffer_head *bh, uint64_t *ptr); > -extern int delete_eattr_indir(struct gfs2_inode *ip, uint64_t block, uint64_t parent, > - struct gfs2_buffer_head **bh, void *private); > -extern int delete_eattr_leaf(struct gfs2_inode *ip, uint64_t block, uint64_t parent, > - struct gfs2_buffer_head **bh, void *private); > -extern int delete_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); > -extern int delete_eattr_extentry(struct gfs2_inode *ip, uint64_t *ea_data_ptr, > - struct gfs2_buffer_head *leaf_bh, > - struct gfs2_ea_header *ea_hdr, > - struct gfs2_ea_header *ea_hdr_prev, > - void *private); > - > extern int _fsck_blockmap_set(struct gfs2_inode *ip, uint64_t bblock, > const char *btype, int mark, int error_on_dinode, > const char *caller, int line); > @@ -57,8 +30,6 @@ extern int check_n_fix_bitmap(struct gfs2_sbd *sdp, uint64_t blk, > extern struct duptree *dupfind(uint64_t block); > extern struct gfs2_inode *fsck_system_inode(struct gfs2_sbd *sdp, > uint64_t block); > -extern int find_remove_dup(struct gfs2_inode *ip, uint64_t block, > - const char *btype); > > #define is_duplicate(dblock) ((dupfind(dblock)) ? 1 : 0) > > @@ -154,6 +125,9 @@ struct metawalk_fxns { > int h, void *private); > int (*undo_check_data) (struct gfs2_inode *ip, uint64_t block, > void *private); > + int (*delete_block) (struct gfs2_inode *ip, uint64_t block, > + struct gfs2_buffer_head **bh, const char *btype, > + void *private); > }; > > #endif /* _METAWALK_H */ > diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c > index d12e03e..fbacfea 100644 > --- a/gfs2/fsck/pass1.c > +++ b/gfs2/fsck/pass1.c > @@ -83,6 +83,22 @@ static int invalidate_eattr_leaf(struct gfs2_inode *ip, uint64_t block, > uint64_t parent, struct gfs2_buffer_head **bh, > void *private); > static int handle_ip(struct gfs2_sbd *sdp, struct gfs2_inode *ip); > +static int delete_block(struct gfs2_inode *ip, uint64_t block, > + struct gfs2_buffer_head **bh, const char *btype, > + void *private); > +/** > + * delete_block - delete a block associated with an inode > + */ > +static int delete_block(struct gfs2_inode *ip, uint64_t block, > + struct gfs2_buffer_head **bh, const char *btype, > + void *private) > +{ > + if (valid_block(ip->i_sbd, block)) { > + fsck_blockmap_set(ip, block, btype, GFS2_BLKST_FREE); > + return 0; > + } > + return -1; > +} > > struct metawalk_fxns pass1_fxns = { > .private = NULL, > @@ -97,6 +113,7 @@ struct metawalk_fxns pass1_fxns = { > .big_file_msg = big_file_comfort, > .undo_check_meta = undo_check_metalist, > .undo_check_data = undo_check_data, > + .delete_block = delete_block, > }; > > struct metawalk_fxns invalidate_fxns = { > @@ -106,6 +123,7 @@ struct metawalk_fxns invalidate_fxns = { > .check_leaf = invalidate_leaf, > .check_eattr_indir = invalidate_eattr_indir, > .check_eattr_leaf = invalidate_eattr_leaf, > + .delete_block = delete_block, > }; > > /* > @@ -200,6 +218,7 @@ struct metawalk_fxns sysdir_fxns = { > .private = NULL, > .check_metalist = resuscitate_metalist, > .check_dentry = resuscitate_dentry, > + .delete_block = delete_block, > }; > > static int p1check_leaf(struct gfs2_inode *ip, uint64_t block, void *private) > @@ -1124,6 +1143,7 @@ struct metawalk_fxns rangecheck_fxns = { > .check_leaf = rangecheck_leaf, > .check_eattr_indir = rangecheck_eattr_indir, > .check_eattr_leaf = rangecheck_eattr_leaf, > + .delete_block = delete_block, > }; > > struct metawalk_fxns eattr_undo_fxns = { > @@ -1131,6 +1151,7 @@ struct metawalk_fxns eattr_undo_fxns = { > .check_eattr_indir = undo_eattr_indir_or_leaf, > .check_eattr_leaf = undo_eattr_indir_or_leaf, > .finish_eattr_indir = finish_eattr_indir, > + .delete_block = delete_block, > }; > /* set_ip_blockmap - set the blockmap for a dinode > * > @@ -1252,6 +1273,7 @@ struct metawalk_fxns alloc_fxns = { > .check_eattr_entry = NULL, > .check_eattr_extentry = NULL, > .finish_eattr_indir = NULL, > + .delete_block = delete_block, > }; > > /* > diff --git a/gfs2/fsck/pass1b.c b/gfs2/fsck/pass1b.c > index 20b603c..a9632d8 100644 > --- a/gfs2/fsck/pass1b.c > +++ b/gfs2/fsck/pass1b.c > @@ -15,6 +15,7 @@ > #include "util.h" > #include "metawalk.h" > #include "inode_hash.h" > +#include "afterpass1_common.h" > > struct fxn_info { > uint64_t block; > diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c > index a215b3c..02d82e4 100644 > --- a/gfs2/fsck/pass2.c > +++ b/gfs2/fsck/pass2.c > @@ -17,6 +17,7 @@ > #include "link.h" > #include "lost_n_found.h" > #include "inode_hash.h" > +#include "afterpass1_common.h" > > #define MAX_FILENAME 256 > > diff --git a/gfs2/fsck/pass3.c b/gfs2/fsck/pass3.c > index 0df427d..d5f4ea2 100644 > --- a/gfs2/fsck/pass3.c > +++ b/gfs2/fsck/pass3.c > @@ -16,6 +16,7 @@ > #include "link.h" > #include "metawalk.h" > #include "util.h" > +#include "afterpass1_common.h" > > static int attach_dotdot_to(struct gfs2_sbd *sdp, uint64_t newdotdot, > uint64_t olddotdot, uint64_t block) > diff --git a/gfs2/fsck/pass4.c b/gfs2/fsck/pass4.c > index ba38e8c..0d6cc9d 100644 > --- a/gfs2/fsck/pass4.c > +++ b/gfs2/fsck/pass4.c > @@ -13,6 +13,7 @@ > #include "inode_hash.h" > #include "metawalk.h" > #include "util.h" > +#include "afterpass1_common.h" > > struct metawalk_fxns pass4_fxns_delete = { > .private = NULL, >