Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2025
February
January
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
List overview
Download
cluster-commits
January 2010
----- 2025 -----
February 2025
January 2025
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
cluster-commits@lists.stg.fedorahosted.org
7 participants
186 discussions
Start a n
N
ew thread
cluster: STABLE3 - fsck.gfs2: convert inode hash to rbtree
by Bob Peterson
26 Jan '10
26 Jan '10
Gitweb:
http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=74…
Commit: 7471efad8ae060d70803bbf66d21e9a36abdd3a5 Parent: 4182a036b732bfadad49f4b886b935c7ef431000 Author: Bob Peterson <bob(a)ganesha.peterson> AuthorDate: Thu Jan 21 14:01:44 2010 -0600 Committer: Bob Peterson <rpeterso(a)redhat.com> CommitterDate: Tue Jan 26 14:39:29 2010 -0600 fsck.gfs2: convert inode hash to rbtree This patch converts the inode hash table to an rbtree to speed things up. rhbz#455300 --- gfs2/fsck/fsck.h | 4 +- gfs2/fsck/initialize.c | 29 +++++++-------- gfs2/fsck/inode_hash.c | 95 ++++++++++++++++++++++-------------------------- gfs2/fsck/inode_hash.h | 9 +++-- gfs2/fsck/link.c | 61 +++++++++---------------------- gfs2/fsck/link.h | 2 +- gfs2/fsck/main.c | 3 +- gfs2/fsck/pass1.c | 3 +- gfs2/fsck/pass1b.c | 8 +++-- gfs2/fsck/pass4.c | 37 +++++++------------ 10 files changed, 104 insertions(+), 147 deletions(-) diff --git a/gfs2/fsck/fsck.h b/gfs2/fsck/fsck.h index 3d52b00..5948210 100644 --- a/gfs2/fsck/fsck.h +++ b/gfs2/fsck/fsck.h @@ -25,7 +25,7 @@ struct inode_info { - osi_list_t list; + struct osi_node node; uint64_t inode; uint16_t link_count; /* the number of links the inode * thinks it has */ @@ -114,7 +114,6 @@ struct dir_info *dirtree_insert(uint64_t dblock); extern struct gfs2_options opts; extern struct gfs2_inode *lf_dip; /* Lost and found directory inode */ -extern osi_list_t inode_hash[FSCK_HASH_SIZE]; extern struct gfs2_bmap *bl; extern uint64_t last_fs_block, last_reported_block; extern int64_t last_reported_fblock; @@ -124,5 +123,6 @@ extern uint64_t last_data_block; extern uint64_t first_data_block; extern struct osi_root dup_blocks; extern struct osi_root dirtree; +extern struct osi_root inodetree; #endif /* _FSCK_H */ diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c index 971decd..00d4ed2 100644 --- a/gfs2/fsck/initialize.c +++ b/gfs2/fsck/initialize.c @@ -16,6 +16,8 @@ #include "fsck.h" #include "util.h" #include "fs_recovery.h" +#include "metawalk.h" +#include "inode_hash.h" #define CLEAR_POINTER(x) \ if(x) { \ @@ -77,6 +79,17 @@ static void gfs2_dirtree_free(void) } } +static void gfs2_inodetree_free(void) +{ + struct osi_node *n; + struct inode_info *dt; + + while ((n = osi_first(&inodetree))) { + dt = (struct inode_info *)n; + inodetree_delete(dt); + } +} + /* * empty_super_block - free all structures in the super block * sdp: the in-core super block @@ -88,22 +101,12 @@ static void gfs2_dirtree_free(void) */ static void empty_super_block(struct gfs2_sbd *sdp) { - uint32_t i; - log_info( _("Freeing buffers.\n")); gfs2_rgrp_free(&sdp->rglist); - for(i = 0; i < FSCK_HASH_SIZE; i++) { - while(!osi_list_empty(&inode_hash[i])) { - struct inode_info *ii; - ii = osi_list_entry(inode_hash[i].next, struct inode_info, list); - osi_list_del(&ii->list); - free(ii); - } - } - if (bl) gfs2_bmap_destroy(sdp, bl); + gfs2_inodetree_free(); gfs2_dirtree_free(); gfs2_dup_free(); } @@ -412,8 +415,6 @@ static int init_system_inodes(struct gfs2_sbd *sdp) */ static int fill_super_block(struct gfs2_sbd *sdp) { - uint32_t i; - sync(); /******************************************************************** @@ -421,8 +422,6 @@ static int fill_super_block(struct gfs2_sbd *sdp) ********************************************************************/ log_info( _("Initializing lists...\n")); osi_list_init(&sdp->rglist); - for(i = 0; i < FSCK_HASH_SIZE; i++) - osi_list_init(&inode_hash[i]); /******************************************************************** ************ next, read in on-disk SB and set constants ********** diff --git a/gfs2/fsck/inode_hash.c b/gfs2/fsck/inode_hash.c index 45efe09..2ba1d05 100644 --- a/gfs2/fsck/inode_hash.c +++ b/gfs2/fsck/inode_hash.c @@ -1,77 +1,68 @@ #include <stdint.h> #include <unistd.h> +#include <libintl.h> #include "libgfs2.h" #include "osi_list.h" #include "hash.h" #include "inode_hash.h" #include "fsck.h" +#define _(String) gettext(String) -static uint32_t gfs2_inode_hash(uint64_t block_no) +struct inode_info *inodetree_find(uint64_t block) { - unsigned int h; + struct osi_node *node = inodetree.osi_node; - h = fsck_hash(&block_no, sizeof (uint64_t)); - h &= FSCK_HASH_MASK; + while (node) { + struct inode_info *data = (struct inode_info *)node; - return h; -} - -struct inode_info *inode_hash_search(osi_list_t *buckets, uint64_t key) -{ - struct inode_info *ii; - osi_list_t *tmp; - osi_list_t *bucket = &buckets[gfs2_inode_hash(key)]; - - osi_list_foreach(tmp, bucket) { - ii = osi_list_entry(tmp, struct inode_info, list); - if(ii->inode == key) { - return ii; - } + if (block < data->inode) + node = node->osi_left; + else if (block > data->inode) + node = node->osi_right; + else + return data; } return NULL; } -int inode_hash_insert(osi_list_t *buckets, uint64_t key, struct inode_info *ii) +struct inode_info *inodetree_insert(uint64_t dblock) { - osi_list_t *tmp; - osi_list_t *bucket = &buckets[gfs2_inode_hash(key)]; - struct inode_info *itmp = NULL; + struct osi_node **newn = &inodetree.osi_node, *parent = NULL; + struct inode_info *data; + + /* Figure out where to put new node */ + while (*newn) { + struct inode_info *cur = (struct inode_info *)*newn; - if(osi_list_empty(bucket)) { - osi_list_add(&ii->list, bucket); - return 0; + parent = *newn; + if (dblock < cur->inode) + newn = &((*newn)->osi_left); + else if (dblock > cur->inode) + newn = &((*newn)->osi_right); + else + return cur; } - osi_list_foreach(tmp, bucket) { - itmp = osi_list_entry(tmp, struct inode_info, list); - if(itmp->inode < key) { - continue; - } else { - osi_list_add_prev(&ii->list, tmp); - return 0; - } + data = malloc(sizeof(struct inode_info)); + if (!data) { + log_crit( _("Unable to allocate inode_info structure\n")); + return NULL; } - osi_list_add_prev(&ii->list, bucket); - return 0; -} + if (!memset(data, 0, sizeof(struct inode_info))) { + log_crit( _("Error while zeroing inode_info structure\n")); + return NULL; + } + /* Add new node and rebalance tree. */ + data->inode = dblock; + osi_link_node(&data->node, parent, newn); + osi_insert_color(&data->node, &inodetree); + return data; +} -int inode_hash_remove(osi_list_t *buckets, uint64_t key) +void inodetree_delete(struct inode_info *b) { - osi_list_t *tmp; - osi_list_t *bucket = &buckets[gfs2_inode_hash(key)]; - struct inode_info *itmp = NULL; - - if(osi_list_empty(bucket)) { - return -1; - } - osi_list_foreach(tmp, bucket) { - itmp = osi_list_entry(tmp, struct inode_info, list); - if(itmp->inode == key) { - osi_list_del(tmp); - return 0; - } - } - return -1; + osi_erase(&b->node, &inodetree); + free(b); } diff --git a/gfs2/fsck/inode_hash.h b/gfs2/fsck/inode_hash.h index 7e41180..e18022d 100644 --- a/gfs2/fsck/inode_hash.h +++ b/gfs2/fsck/inode_hash.h @@ -1,9 +1,10 @@ #ifndef _INODE_HASH_H #define _INODE_HASH_H -struct inode_info *inode_hash_search(osi_list_t *buckets, uint64_t block_no); -int inode_hash_insert(osi_list_t *buckets, uint64_t key, - struct inode_info *ii); -int inode_hash_remove(osi_list_t *buckets, uint64_t key); +struct inode_info; + +extern struct inode_info *inodetree_find(uint64_t block); +extern struct inode_info *inodetree_insert(uint64_t dblock); +extern void inodetree_delete(struct inode_info *b); #endif /* _INODE_HASH_H */ diff --git a/gfs2/fsck/link.c b/gfs2/fsck/link.c index 9666f63..59e258b 100644 --- a/gfs2/fsck/link.c +++ b/gfs2/fsck/link.c @@ -11,37 +11,19 @@ #include "inode_hash.h" #include "link.h" -int set_link_count(struct gfs2_sbd *sbp, uint64_t inode_no, uint32_t count) +int set_link_count(uint64_t inode_no, uint32_t count) { - struct inode_info *ii = NULL; - log_debug( _("Setting link count to %u for %" PRIu64 " (0x%" PRIx64 ")\n"), - count, inode_no, inode_no); - /* If the list has entries, look for one that matches - * inode_no */ - ii = inode_hash_search(inode_hash, inode_no); - if(ii) { - if(ii->link_count) { - log_err( _("Link count already set for inode #%" PRIu64 " (0x%" - PRIx64 ")!\n"), inode_no, inode_no); - stack; - return -1; - } - else - ii->link_count = count; - } - else { - /* If not match was found, add a new entry and set it's - * link count to count*/ - if(!(ii = (struct inode_info *) malloc(sizeof(*ii)))) { - log_err( _("Unable to allocate inode_info structure\n")); - stack; - return -1; - } - memset(ii, 0, sizeof(*ii)); - ii->inode = inode_no; + struct inode_info *ii; + /*log_debug( _("Setting link count to %u for %" PRIu64 + " (0x%" PRIx64 ")\n"), count, inode_no, inode_no);*/ + /* If the list has entries, look for one that matches inode_no */ + ii = inodetree_find(inode_no); + if (!ii) + ii = inodetree_insert(inode_no); + if (ii) ii->link_count = count; - inode_hash_insert(inode_hash, inode_no, ii); - } + else + return -1; return 0; } @@ -49,7 +31,7 @@ int increment_link(struct gfs2_sbd *sbp, uint64_t inode_no) { struct inode_info *ii = NULL; - ii = inode_hash_search(inode_hash, inode_no); + ii = inodetree_find(inode_no); /* If the list has entries, look for one that matches * inode_no */ if(ii) { @@ -62,20 +44,11 @@ int increment_link(struct gfs2_sbd *sbp, uint64_t inode_no) " (0x%" PRIx64 ")!\n"), inode_no, inode_no); /* If no match was found, add a new entry and set its * counted links to 1 */ - if(!(ii = (struct inode_info *) malloc(sizeof(*ii)))) { - log_err( _("Unable to allocate inode_info structure\n")); - stack; - return -1; - } - if(!memset(ii, 0, sizeof(*ii))) { - log_err( _("Unable to zero inode_info structure\n")); - stack; + ii = inodetree_insert(inode_no); + if (ii) + ii->counted_links = 1; + else return -1; - } - ii->inode = inode_no; - ii->counted_links = 1; - inode_hash_insert(inode_hash, inode_no, ii); - return 0; } @@ -83,7 +56,7 @@ int decrement_link(struct gfs2_sbd *sbp, uint64_t inode_no) { struct inode_info *ii = NULL; - ii = inode_hash_search(inode_hash, inode_no); + ii = inodetree_find(inode_no); /* If the list has entries, look for one that matches * inode_no */ log_err( _("Decrementing %"PRIu64" (0x%" PRIx64 ")\n"), inode_no, inode_no); diff --git a/gfs2/fsck/link.h b/gfs2/fsck/link.h index becede1..7446b4a 100644 --- a/gfs2/fsck/link.h +++ b/gfs2/fsck/link.h @@ -1,7 +1,7 @@ #ifndef _LINK_H #define _LINK_H -int set_link_count(struct gfs2_sbd *sbp, uint64_t inode_no, uint32_t count); +int set_link_count(uint64_t inode_no, uint32_t count); int increment_link(struct gfs2_sbd *sbp, uint64_t inode_no); int decrement_link(struct gfs2_sbd *sbp, uint64_t inode_no); diff --git a/gfs2/fsck/main.c b/gfs2/fsck/main.c index f9c5fa3..ffac5e7 100644 --- a/gfs2/fsck/main.c +++ b/gfs2/fsck/main.c @@ -19,8 +19,6 @@ struct gfs2_options opts = {0}; struct gfs2_inode *lf_dip; /* Lost and found directory inode */ -osi_list_t dir_hash[FSCK_HASH_SIZE]; -osi_list_t inode_hash[FSCK_HASH_SIZE]; struct gfs2_bmap *bl = NULL; uint64_t last_fs_block, last_reported_block = -1; int64_t last_reported_fblock = -1000000; @@ -32,6 +30,7 @@ uint64_t first_data_block; int preen = 0, force_check = 0; struct osi_root dup_blocks = (struct osi_root) { NULL, }; struct osi_root dirtree = (struct osi_root) { NULL, }; +struct osi_root inodetree = (struct osi_root) { NULL, }; /* This function is for libgfs2's sake. */ void print_it(const char *label, const char *fmt, const char *fmt2, ...) diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c index 2cd8bdc..0070886 100644 --- a/gfs2/fsck/pass1.c +++ b/gfs2/fsck/pass1.c @@ -21,6 +21,7 @@ #include "libgfs2.h" #include "fsck.h" +#include "inode_hash.h" #include "util.h" #include "link.h" #include "metawalk.h" @@ -709,7 +710,7 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh, fsck_inode_put(&ip); return 0; } - if(set_link_count(ip->i_sbd, ip->i_di.di_num.no_addr, ip->i_di.di_nlink)) { + if(set_link_count(ip->i_di.di_num.no_addr, ip->i_di.di_nlink)) { stack; fsck_inode_put(&ip); return -1; diff --git a/gfs2/fsck/pass1b.c b/gfs2/fsck/pass1b.c index 9e1c20f..1ee0ebd 100644 --- a/gfs2/fsck/pass1b.c +++ b/gfs2/fsck/pass1b.c @@ -163,7 +163,6 @@ static int clear_dup_metalist(struct gfs2_inode *ip, uint64_t block, log_err( _("Inode %s is in directory %"PRIu64" (0x%" PRIx64 ")\n"), dh->id->name ? dh->id->name : "", dh->id->parent, dh->id->parent); - inode_hash_remove(inode_hash, ip->i_di.di_num.no_addr); /* Setting the block to invalid means the inode is * cleared in pass2 */ gfs2_blockmap_set(ip->i_sbd, bl, ip->i_di.di_num.no_addr, @@ -408,12 +407,15 @@ static int handle_dup_blk(struct gfs2_sbd *sbp, struct duptree *b) (unsigned long long)b->block, (unsigned long long)b->block); if (query( _("Clear the inode? (y/n) "))) { + struct inode_info *ii; + log_warn( _("Clearing inode %lld (0x%llx)...\n"), (unsigned long long)id->block_no, (unsigned long long)id->block_no); ip = fsck_load_inode(sbp, id->block_no); - inode_hash_remove(inode_hash, - ip->i_di.di_num.no_addr); + ii = inodetree_find(ip->i_di.di_num.no_addr); + if (ii) + inodetree_delete(ii); /* Setting the block to invalid means the inode is cleared in pass2 */ gfs2_blockmap_set(ip->i_sbd, bl, diff --git a/gfs2/fsck/pass4.c b/gfs2/fsck/pass4.c index a28dec6..efcf70d 100644 --- a/gfs2/fsck/pass4.c +++ b/gfs2/fsck/pass4.c @@ -21,8 +21,7 @@ struct metawalk_fxns pass4_fxns_delete = { /* Updates the link count of an inode to what the fsck has seen for * link count */ -static int fix_inode_count(struct gfs2_sbd *sbp, struct inode_info *ii, - struct gfs2_inode *ip) +static int fix_link_count(struct inode_info *ii, struct gfs2_inode *ip) { log_info( _("Fixing inode link count (%d->%d) for %llu (0x%llx) \n"), ip->i_di.di_nlink, ii->counted_links, @@ -40,8 +39,8 @@ static int fix_inode_count(struct gfs2_sbd *sbp, struct inode_info *ii, return 0; } -static int scan_inode_list(struct gfs2_sbd *sbp, osi_list_t *list) { - osi_list_t *tmp; +static int scan_inode_list(struct gfs2_sbd *sbp) { + struct osi_node *tmp; struct inode_info *ii; struct gfs2_inode *ip; int lf_addition = 0; @@ -49,11 +48,11 @@ static int scan_inode_list(struct gfs2_sbd *sbp, osi_list_t *list) { /* FIXME: should probably factor this out into a generic * scanning fxn */ - osi_list_foreach(tmp, list) { + for (tmp = osi_first(&inodetree); tmp; tmp = osi_next(tmp)) { if (skip_this_pass || fsck_abort) /* if asked to skip the rest */ return 0; - if(!(ii = osi_list_entry(tmp, struct inode_info, list))) { - log_crit( _("osi_list_foreach broken in scan_info_list!!\n")); + if(!(ii = (struct inode_info *)tmp)) { + log_crit( _("osi_tree broken in scan_info_list!!\n")); exit(FSCK_ERROR); } if(ii->counted_links == 0) { @@ -129,7 +128,7 @@ static int scan_inode_list(struct gfs2_sbd *sbp, osi_list_t *list) { fsck_inode_put(&ip); return -1; } else { - fix_inode_count(sbp, ii, ip); + fix_link_count(ii, ip); lf_addition = 1; } } else @@ -146,8 +145,8 @@ static int scan_inode_list(struct gfs2_sbd *sbp, osi_list_t *list) { " (0x%" PRIx64 ") ? (y/n) "), ii->inode, ii->inode)) { ip = fsck_load_inode(sbp, ii->inode); /* bread, inode_get */ - fix_inode_count(sbp, ii, ip); - bmodified(ip->i_bh); + fix_link_count(ii, ip); + ii->link_count = ii->counted_links; fsck_inode_put(&ip); /* out, brelse, free */ log_warn( _("Link count updated to %d for " "inode %" PRIu64 " (0x%" @@ -163,12 +162,11 @@ static int scan_inode_list(struct gfs2_sbd *sbp, osi_list_t *list) { } /* osi_list_foreach(tmp, list) */ if (lf_addition) { - if(!(ii = inode_hash_search(inode_hash, - lf_dip->i_di.di_num.no_addr))) { + if(!(ii = inodetree_find(lf_dip->i_di.di_num.no_addr))) { log_crit( _("Unable to find lost+found inode in inode_hash!!\n")); return -1; } else { - fix_inode_count(sbp, ii, lf_dip); + fix_link_count(ii, lf_dip); } } @@ -186,20 +184,13 @@ static int scan_inode_list(struct gfs2_sbd *sbp, osi_list_t *list) { */ int pass4(struct gfs2_sbd *sbp) { - uint32_t i; - osi_list_t *list; if(lf_dip) log_debug( _("At beginning of pass4, lost+found entries is %u\n"), lf_dip->i_di.di_entries); log_info( _("Checking inode reference counts.\n")); - for (i = 0; i < FSCK_HASH_SIZE; i++) { - if (skip_this_pass || fsck_abort) /* if asked to skip the rest */ - return FSCK_OK; - list = &inode_hash[i]; - if(scan_inode_list(sbp, list)) { - stack; - return FSCK_ERROR; - } + if(scan_inode_list(sbp)) { + stack; + return FSCK_ERROR; } if(lf_dip)
1
0
0
0
cluster: STABLE3 - fsck.gfs2: convert dir_info list to rbtree
by Bob Peterson
26 Jan '10
26 Jan '10
Gitweb:
http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=41…
Commit: 4182a036b732bfadad49f4b886b935c7ef431000 Parent: 35c2c9b2a295ae79231107d4861caae97cb31053 Author: Bob Peterson <bob(a)ganesha.peterson> AuthorDate: Thu Jan 21 13:12:15 2010 -0600 Committer: Bob Peterson <rpeterso(a)redhat.com> CommitterDate: Tue Jan 26 14:39:29 2010 -0600 fsck.gfs2: convert dir_info list to rbtree This patch replaces the linked list of directories with another rbtree to speedy things up. rhbz#455300 --- gfs2/fsck/fsck.h | 6 ++-- gfs2/fsck/initialize.c | 22 ++++++++------ gfs2/fsck/main.c | 7 ++-- gfs2/fsck/metawalk.c | 73 ------------------------------------------------ gfs2/fsck/metawalk.h | 5 --- gfs2/fsck/pass1.c | 32 +-------------------- gfs2/fsck/pass2.c | 10 ++++-- gfs2/fsck/pass3.c | 19 +++++------- gfs2/fsck/util.c | 58 ++++++++++++++++++++++++++++++++++++++ 9 files changed, 92 insertions(+), 140 deletions(-) diff --git a/gfs2/fsck/fsck.h b/gfs2/fsck/fsck.h index d04168b..3d52b00 100644 --- a/gfs2/fsck/fsck.h +++ b/gfs2/fsck/fsck.h @@ -34,7 +34,7 @@ struct inode_info struct dir_info { - osi_list_t list; + struct osi_node node; uint64_t dinode; uint64_t treewalk_parent; uint64_t dotdot_parent; @@ -110,11 +110,10 @@ extern void dirtree_delete(struct dir_info *b); /* FIXME: Hack to get this going for pass2 - this should be pulled out * of pass1 and put somewhere else... */ -int add_to_dir_list(struct gfs2_sbd *sbp, uint64_t block); +struct dir_info *dirtree_insert(uint64_t dblock); extern struct gfs2_options opts; extern struct gfs2_inode *lf_dip; /* Lost and found directory inode */ -extern osi_list_t dir_hash[FSCK_HASH_SIZE]; extern osi_list_t inode_hash[FSCK_HASH_SIZE]; extern struct gfs2_bmap *bl; extern uint64_t last_fs_block, last_reported_block; @@ -124,5 +123,6 @@ extern int errors_found, errors_corrected; extern uint64_t last_data_block; extern uint64_t first_data_block; extern struct osi_root dup_blocks; +extern struct osi_root dirtree; #endif /* _FSCK_H */ diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c index 81194c5..971decd 100644 --- a/gfs2/fsck/initialize.c +++ b/gfs2/fsck/initialize.c @@ -66,6 +66,17 @@ void gfs2_dup_free(void) } } +static void gfs2_dirtree_free(void) +{ + struct osi_node *n; + struct dir_info *dt; + + while ((n = osi_first(&dirtree))) { + dt = (struct dir_info *)n; + dirtree_delete(dt); + } +} + /* * empty_super_block - free all structures in the super block * sdp: the in-core super block @@ -89,16 +100,11 @@ static void empty_super_block(struct gfs2_sbd *sdp) osi_list_del(&ii->list); free(ii); } - while(!osi_list_empty(&dir_hash[i])) { - struct dir_info *di; - di = osi_list_entry(dir_hash[i].next, struct dir_info, list); - osi_list_del(&di->list); - free(di); - } } if (bl) gfs2_bmap_destroy(sdp, bl); + gfs2_dirtree_free(); gfs2_dup_free(); } @@ -415,10 +421,8 @@ static int fill_super_block(struct gfs2_sbd *sdp) ********************************************************************/ log_info( _("Initializing lists...\n")); osi_list_init(&sdp->rglist); - for(i = 0; i < FSCK_HASH_SIZE; i++) { - osi_list_init(&dir_hash[i]); + for(i = 0; i < FSCK_HASH_SIZE; i++) osi_list_init(&inode_hash[i]); - } /******************************************************************** ************ next, read in on-disk SB and set constants ********** diff --git a/gfs2/fsck/main.c b/gfs2/fsck/main.c index b75f012..f9c5fa3 100644 --- a/gfs2/fsck/main.c +++ b/gfs2/fsck/main.c @@ -31,6 +31,7 @@ uint64_t last_data_block; uint64_t first_data_block; int preen = 0, force_check = 0; struct osi_root dup_blocks = (struct osi_root) { NULL, }; +struct osi_root dirtree = (struct osi_root) { NULL, }; /* This function is for libgfs2's sake. */ void print_it(const char *label, const char *fmt, const char *fmt2, ...) @@ -174,8 +175,7 @@ static int check_system_inode(struct gfs2_inode *sysinode, const char *filename, mark); ds.q = mark; if (mark == gfs2_inode_dir) - add_to_dir_list(sysinode->i_sbd, - sysinode->i_di.di_num.no_addr); + dirtree_insert(sysinode->i_di.di_num.no_addr); } } else @@ -193,8 +193,7 @@ static int check_system_inode(struct gfs2_inode *sysinode, const char *filename, mark); ds.q = mark; if (mark == gfs2_inode_dir) - add_to_dir_list(sysinode->i_sbd, - sysinode->i_di.di_num.no_addr); + dirtree_insert(sysinode->i_di.di_num.no_addr); } else { log_err( _("Cannot continue without valid %s inode\n"), diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c index dad6d34..d5a29b7 100644 --- a/gfs2/fsck/metawalk.c +++ b/gfs2/fsck/metawalk.c @@ -1113,79 +1113,6 @@ int remove_dentry_from_dir(struct gfs2_sbd *sbp, uint64_t dir, return error; } -/* FIXME: These should be merged with the hash routines in inode_hash.c */ -static uint32_t dinode_hash(uint64_t block_no) -{ - unsigned int h; - - h = fsck_hash(&block_no, sizeof (uint64_t)); - h &= FSCK_HASH_MASK; - - return h; -} - -int find_di(struct gfs2_sbd *sbp, uint64_t childblock, struct dir_info **dip) -{ - osi_list_t *bucket = &dir_hash[dinode_hash(childblock)]; - osi_list_t *tmp; - struct dir_info *di = NULL; - - osi_list_foreach(tmp, bucket) { - di = osi_list_entry(tmp, struct dir_info, list); - if(di->dinode == childblock) { - *dip = di; - return 0; - } - } - *dip = NULL; - return -1; - -} - -int dinode_hash_insert(osi_list_t *buckets, uint64_t key, struct dir_info *di) -{ - osi_list_t *tmp; - osi_list_t *bucket = &buckets[dinode_hash(key)]; - struct dir_info *dtmp = NULL; - - if(osi_list_empty(bucket)) { - osi_list_add(&di->list, bucket); - return 0; - } - - osi_list_foreach(tmp, bucket) { - dtmp = osi_list_entry(tmp, struct dir_info, list); - if(dtmp->dinode < key) { - continue; - } - else { - osi_list_add_prev(&di->list, tmp); - return 0; - } - } - osi_list_add_prev(&di->list, bucket); - return 0; -} - -int dinode_hash_remove(osi_list_t *buckets, uint64_t key) -{ - osi_list_t *tmp; - osi_list_t *bucket = &buckets[dinode_hash(key)]; - struct dir_info *dtmp = NULL; - - if(osi_list_empty(bucket)) { - return -1; - } - osi_list_foreach(tmp, bucket) { - dtmp = osi_list_entry(tmp, struct dir_info, list); - if(dtmp->dinode == key) { - osi_list_del(tmp); - return 0; - } - } - return -1; -} - /** * delete_blocks - delete blocks associated with an inode */ diff --git a/gfs2/fsck/metawalk.h b/gfs2/fsck/metawalk.h index dbbe4c3..9710b01 100644 --- a/gfs2/fsck/metawalk.h +++ b/gfs2/fsck/metawalk.h @@ -15,11 +15,6 @@ extern int check_linear_dir(struct gfs2_inode *ip, struct gfs2_buffer_head *bh, struct metawalk_fxns *pass); extern int remove_dentry_from_dir(struct gfs2_sbd *sbp, uint64_t dir, uint64_t dentryblock); -extern int find_di(struct gfs2_sbd *sbp, uint64_t childblock, - struct dir_info **dip); -extern int dinode_hash_insert(osi_list_t *buckets, uint64_t key, - struct dir_info *di); -extern int dinode_hash_remove(osi_list_t *buckets, uint64_t key); extern int delete_blocks(struct gfs2_inode *ip, uint64_t block, struct gfs2_buffer_head **bh, const char *btype, void *private); diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c index 6862f29..2cd8bdc 100644 --- a/gfs2/fsck/pass1.c +++ b/gfs2/fsck/pass1.c @@ -587,36 +587,6 @@ static int clear_leaf(struct gfs2_inode *ip, uint64_t block, return 0; } -int add_to_dir_list(struct gfs2_sbd *sbp, uint64_t block) -{ - struct dir_info *di = NULL; - struct dir_info *newdi; - - /* FIXME: This list should probably be a b-tree or - * something...but since most of the time we're going to be - * tacking the directory onto the end of the list, it doesn't - * matter too much */ - find_di(sbp, block, &di); - if(di) { - log_err( _("Attempting to add directory block #%" PRIu64 - " (0x%" PRIx64 ") which is already in list\n"), block, block); - return -1; - } - - if(!(newdi = (struct dir_info *) malloc(sizeof(struct dir_info)))) { - log_crit( _("Unable to allocate dir_info structure\n")); - return -1; - } - if(!memset(newdi, 0, sizeof(*newdi))) { - log_crit( _("Error while zeroing dir_info structure\n")); - return -1; - } - - newdi->dinode = block; - dinode_hash_insert(dir_hash, block, newdi); - return 0; -} - static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh, uint64_t block) { @@ -667,7 +637,7 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh, fsck_inode_put(&ip); return -1; } - if(add_to_dir_list(sdp, block)) { + if(!dirtree_insert(block)) { stack; fsck_inode_put(&ip); return -1; diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c index 90f6572..a368124 100644 --- a/gfs2/fsck/pass2.c +++ b/gfs2/fsck/pass2.c @@ -23,7 +23,8 @@ static int set_parent_dir(struct gfs2_sbd *sbp, uint64_t childblock, { struct dir_info *di; - if(!find_di(sbp, childblock, &di)) { + di = dirtree_find(childblock); + if (di) { if(di->dinode == childblock) { if (di->treewalk_parent) { log_err( _("Another directory at block %" PRIu64 @@ -50,7 +51,8 @@ static int set_dotdot_dir(struct gfs2_sbd *sbp, uint64_t childblock, { struct dir_info *di; - if(!find_di(sbp, childblock, &di)) { + di = dirtree_find(childblock); + if(di) { if(di->dinode == childblock) { /* Special case for root inode because we set * it earlier */ @@ -722,8 +724,8 @@ int pass2(struct gfs2_sbd *sbp) if (error > 0) { struct dir_info *di = NULL; - error = find_di(sbp, dirblk, &di); - if(error < 0) { + di = dirtree_find(dirblk); + if(!di) { stack; return FSCK_ERROR; } diff --git a/gfs2/fsck/pass3.c b/gfs2/fsck/pass3.c index c1986f3..fd34de2 100644 --- a/gfs2/fsck/pass3.c +++ b/gfs2/fsck/pass3.c @@ -150,7 +150,7 @@ static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sbp, return NULL; } } - find_di(sbp, di->dotdot_parent, &pdi); + pdi = dirtree_find(di->dotdot_parent); return pdi; } @@ -163,19 +163,18 @@ static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sbp, */ int pass3(struct gfs2_sbd *sbp) { - osi_list_t *tmp; + struct osi_node *tmp; struct dir_info *di, *tdi; struct gfs2_inode *ip; uint8_t q; - int i; - find_di(sbp, sbp->md.rooti->i_di.di_num.no_addr, &di); - if(di) { + di = dirtree_find(sbp->md.rooti->i_di.di_num.no_addr); + if (di) { log_info( _("Marking root inode connected\n")); di->checked = 1; } - find_di(sbp, sbp->master_dir->i_di.di_num.no_addr, &di); - if(di) { + di = dirtree_find(sbp->master_dir->i_di.di_num.no_addr); + if (di) { log_info( _("Marking master directory inode connected\n")); di->checked = 1; } @@ -185,9 +184,8 @@ int pass3(struct gfs2_sbd *sbp) * find a parent, put in lost+found. */ log_info( _("Checking directory linkage.\n")); - for(i = 0; i < FSCK_HASH_SIZE; i++) { - osi_list_foreach(tmp, &dir_hash[i]) { - di = osi_list_entry(tmp, struct dir_info, list); + for (tmp = osi_first(&dirtree); tmp; tmp = osi_next(tmp)) { + di = (struct dir_info *)tmp; while(!di->checked) { /* FIXME: Change this so it returns success or * failure and put the parent inode in a @@ -264,7 +262,6 @@ int pass3(struct gfs2_sbd *sbp) di = tdi; } } - } if(lf_dip) log_debug( _("At end of pass3, lost+found entries is %u\n"), lf_dip->i_di.di_entries); diff --git a/gfs2/fsck/util.c b/gfs2/fsck/util.c index 8a89d01..9f2aae0 100644 --- a/gfs2/fsck/util.c +++ b/gfs2/fsck/util.c @@ -181,6 +181,58 @@ struct duptree *gfs2_dup_set(uint64_t dblock) return data; } +struct dir_info *dirtree_insert(uint64_t dblock) +{ + struct osi_node **newn = &dirtree.osi_node, *parent = NULL; + struct dir_info *data; + + /* Figure out where to put new node */ + while (*newn) { + struct dir_info *cur = (struct dir_info *)*newn; + + parent = *newn; + if (dblock < cur->dinode) + newn = &((*newn)->osi_left); + else if (dblock > cur->dinode) + newn = &((*newn)->osi_right); + else + return cur; + } + + data = malloc(sizeof(struct dir_info)); + if (!data) { + log_crit( _("Unable to allocate dir_info structure\n")); + return NULL; + } + if (!memset(data, 0, sizeof(struct dir_info))) { + log_crit( _("Error while zeroing dir_info structure\n")); + return NULL; + } + /* Add new node and rebalance tree. */ + data->dinode = dblock; + osi_link_node(&data->node, parent, newn); + osi_insert_color(&data->node, &dirtree); + + return data; +} + +struct dir_info *dirtree_find(uint64_t block) +{ + struct osi_node *node = dirtree.osi_node; + + while (node) { + struct dir_info *data = (struct dir_info *)node; + + if (block < data->dinode) + node = node->osi_left; + else if (block > data->dinode) + node = node->osi_right; + else + return data; + } + return NULL; +} + void dup_delete(struct duptree *b) { struct inode_with_dups *id; @@ -197,3 +249,9 @@ void dup_delete(struct duptree *b) osi_erase(&b->node, &dup_blocks); free(b); } + +void dirtree_delete(struct dir_info *b) +{ + osi_erase(&b->node, &dirtree); + free(b); +}
1
0
0
0
cluster: STABLE3 - fsck.gfs2: convert dup_list to a rbtree
by Bob Peterson
26 Jan '10
26 Jan '10
Gitweb:
http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=35…
Commit: 35c2c9b2a295ae79231107d4861caae97cb31053 Parent: 5b7d0817560827d007b5ee0927a9dbb414aa1121 Author: Bob Peterson <bob(a)ganesha.peterson> AuthorDate: Thu Jan 21 12:16:10 2010 -0600 Committer: Bob Peterson <rpeterso(a)redhat.com> CommitterDate: Tue Jan 26 14:39:29 2010 -0600 fsck.gfs2: convert dup_list to a rbtree This patch uses a new include file, osi_tree.h to implement the duplicates list as a red-black tree. This will speed up the duplicate processing considerably. rhbz#455300 --- gfs2/fsck/fsck.h | 36 ++++- gfs2/fsck/initialize.c | 23 +-- gfs2/fsck/main.c | 2 +- gfs2/fsck/metawalk.c | 31 ++-- gfs2/fsck/metawalk.h | 2 +- gfs2/fsck/pass1b.c | 39 ++--- gfs2/fsck/pass2.c | 8 +- gfs2/fsck/util.c | 53 +++++-- gfs2/fsck/util.h | 2 +- gfs2/include/osi_tree.h | 395 +++++++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 511 insertions(+), 80 deletions(-) diff --git a/gfs2/fsck/fsck.h b/gfs2/fsck/fsck.h index 7107678..d04168b 100644 --- a/gfs2/fsck/fsck.h +++ b/gfs2/fsck/fsck.h @@ -2,6 +2,7 @@ #define _FSCK_H #include "libgfs2.h" +#include "osi_tree.h" #define FSCK_HASH_SHIFT (13) #define FSCK_HASH_SIZE (1 << FSCK_HASH_SHIFT) @@ -48,6 +49,31 @@ struct dir_status { uint32_t entry_count; }; +struct duptree { + struct osi_node node; + int first_ref_found; /* Has the original reference been found? */ + int refs; + uint64_t block; + osi_list_t ref_inode_list; /* list of inodes referencing a dup block */ + osi_list_t ref_invinode_list; /* list of invalid inodes referencing */ +}; + +enum dup_ref_type { + ref_as_data = 0, + ref_as_meta = 1, + ref_as_ea = 2, + ref_types = 3 +}; + +struct inode_with_dups { + osi_list_t list; + uint64_t block_no; + int dup_count; + int ea_only; + uint64_t parent; + char *name; +}; + enum rgindex_trust_level { /* how far can we trust our RG index? */ blind_faith = 0, /* We'd like to trust the rgindex. We always used to before bz 179069. This should cover most cases. */ @@ -59,12 +85,6 @@ enum rgindex_trust_level { /* how far can we trust our RG index? */ gfs2_grow or something. Count the RGs by hand. */ }; -struct dup_blks { - osi_list_t list; - uint64_t block; - osi_list_t ref_inode_list; -}; - extern struct gfs2_inode *fsck_load_inode(struct gfs2_sbd *sbp, uint64_t block); extern struct gfs2_inode *fsck_inode_get(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh); @@ -81,9 +101,11 @@ extern int pass3(struct gfs2_sbd *sbp); extern int pass4(struct gfs2_sbd *sbp); extern int pass5(struct gfs2_sbd *sbp); extern int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count); +extern void gfs2_dup_free(void); extern int fsck_query(const char *format, ...) __attribute__((format(printf,1,2))); extern struct dir_info *dirtree_find(uint64_t block); +extern void dup_delete(struct duptree *b); extern void dirtree_delete(struct dir_info *b); /* FIXME: Hack to get this going for pass2 - this should be pulled out @@ -101,6 +123,6 @@ extern int skip_this_pass, fsck_abort; extern int errors_found, errors_corrected; extern uint64_t last_data_block; extern uint64_t first_data_block; -extern struct dup_blks dup_blocks; +extern struct osi_root dup_blocks; #endif /* _FSCK_H */ diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c index 79f88fd..81194c5 100644 --- a/gfs2/fsck/initialize.c +++ b/gfs2/fsck/initialize.c @@ -55,17 +55,14 @@ static int block_mounters(struct gfs2_sbd *sbp, int block_em) return 0; } -static void gfs2_dup_free(void) +void gfs2_dup_free(void) { - struct dup_blks *f; - - while(!osi_list_empty(&dup_blocks.list)) { - f = osi_list_entry(dup_blocks.list.next, struct dup_blks, - list); - while (!osi_list_empty(&f->ref_inode_list)) - osi_list_del(&f->ref_inode_list); - osi_list_del(&f->list); - free(f); + struct osi_node *n; + struct duptree *dt; + + while ((n = osi_first(&dup_blocks))) { + dt = (struct duptree *)n; + dup_delete(dt); } } @@ -100,10 +97,9 @@ static void empty_super_block(struct gfs2_sbd *sdp) } } - if (bl) { + if (bl) gfs2_bmap_destroy(sdp, bl); - gfs2_dup_free(); - } + gfs2_dup_free(); } @@ -395,7 +391,6 @@ static int init_system_inodes(struct gfs2_sbd *sdp) log_crit( _("Please increase your swap space by that amount and run gfs2_fsck again.\n")); goto fail; } - osi_list_init(&dup_blocks.list); return 0; fail: empty_super_block(sdp); diff --git a/gfs2/fsck/main.c b/gfs2/fsck/main.c index c2f9722..b75f012 100644 --- a/gfs2/fsck/main.c +++ b/gfs2/fsck/main.c @@ -30,7 +30,7 @@ const char *pass = ""; uint64_t last_data_block; uint64_t first_data_block; int preen = 0, force_check = 0; -struct dup_blks dup_blocks; +struct osi_root dup_blocks = (struct osi_root) { NULL, }; /* This function is for libgfs2's sake. */ void print_it(const char *label, const char *fmt, const char *fmt2, ...) diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c index 6dd46cd..dad6d34 100644 --- a/gfs2/fsck/metawalk.c +++ b/gfs2/fsck/metawalk.c @@ -16,20 +16,6 @@ #define COMFORTABLE_BLKS 5242880 /* 20GB in 4K blocks */ -struct dup_blks *dupfind(uint64_t num) -{ - osi_list_t *head = &dup_blocks.list; - osi_list_t *tmp; - struct dup_blks *b; - - for (tmp = head->next; tmp != head; tmp = tmp->next) { - b = osi_list_entry(tmp, struct dup_blks, list); - if (b->block == num) - return b; - } - return NULL; -} - static struct gfs2_inode *get_system_inode(struct gfs2_sbd *sbp, uint64_t block) { @@ -54,6 +40,23 @@ static struct gfs2_inode *get_system_inode(struct gfs2_sbd *sbp, return is_system_inode(sbp, block); } +struct duptree *dupfind(uint64_t block) +{ + struct osi_node *node = dup_blocks.osi_node; + + while (node) { + struct duptree *data = (struct duptree *)node; + + if (block < data->block) + node = node->osi_left; + else if (block > data->block) + node = node->osi_right; + else + return data; + } + return NULL; +} + /* fsck_load_inode - same as gfs2_load_inode() in libgfs2 but system inodes get special treatment. */ struct gfs2_inode *fsck_load_inode(struct gfs2_sbd *sbp, uint64_t block) diff --git a/gfs2/fsck/metawalk.h b/gfs2/fsck/metawalk.h index c24c705..dbbe4c3 100644 --- a/gfs2/fsck/metawalk.h +++ b/gfs2/fsck/metawalk.h @@ -32,7 +32,7 @@ extern int delete_eattr_indir(struct gfs2_inode *ip, uint64_t block, extern int delete_eattr_leaf(struct gfs2_inode *ip, uint64_t block, uint64_t parent, struct gfs2_buffer_head **bh, void *private); -extern struct dup_blks *dupfind(uint64_t num); +extern struct duptree *dupfind(uint64_t block); #define is_duplicate(dblock) ((dupfind(dblock)) ? 1 : 0) diff --git a/gfs2/fsck/pass1b.c b/gfs2/fsck/pass1b.c index ead608a..9e1c20f 100644 --- a/gfs2/fsck/pass1b.c +++ b/gfs2/fsck/pass1b.c @@ -12,15 +12,6 @@ #include "metawalk.h" #include "inode_hash.h" -struct inode_with_dups { - osi_list_t list; - uint64_t block_no; - int dup_count; - int ea_only; - uint64_t parent; - char *name; -}; - struct fxn_info { uint64_t block; int found; @@ -28,7 +19,7 @@ struct fxn_info { }; struct dup_handler { - struct dup_blks *b; + struct duptree *b; struct inode_with_dups *id; int ref_inode_count; int ref_count; @@ -112,13 +103,14 @@ static int find_dentry(struct gfs2_inode *ip, struct gfs2_dirent *de, struct gfs2_buffer_head *bh, char *filename, uint16_t *count, void *priv) { - osi_list_t *tmp1, *tmp2; - struct dup_blks *b; + struct osi_node *n; + osi_list_t *tmp2; + struct duptree *b; struct inode_with_dups *id; struct gfs2_leaf leaf; - osi_list_foreach(tmp1, &dup_blocks.list) { - b = osi_list_entry(tmp1, struct dup_blks, list); + for (n = osi_first(&dup_blocks); n; n = osi_next(n)) { + b = (struct duptree *)n; osi_list_foreach(tmp2, &b->ref_inode_list) { id = osi_list_entry(tmp2, struct inode_with_dups, list); @@ -313,7 +305,7 @@ static int clear_eattr_extentry(struct gfs2_inode *ip, uint64_t *ea_data_ptr, } /* Finds all references to duplicate blocks in the metadata */ -static int find_block_ref(struct gfs2_sbd *sbp, uint64_t inode, struct dup_blks *b) +static int find_block_ref(struct gfs2_sbd *sbp, uint64_t inode, struct duptree *b) { struct gfs2_inode *ip; struct fxn_info myfi = {b->block, 0, 1}; @@ -367,7 +359,7 @@ static int find_block_ref(struct gfs2_sbd *sbp, uint64_t inode, struct dup_blks return 0; } -static int handle_dup_blk(struct gfs2_sbd *sbp, struct dup_blks *b) +static int handle_dup_blk(struct gfs2_sbd *sbp, struct duptree *b) { osi_list_t *tmp; struct inode_with_dups *id; @@ -491,10 +483,10 @@ static int handle_dup_blk(struct gfs2_sbd *sbp, struct dup_blks *b) * use in pass2 */ int pass1b(struct gfs2_sbd *sbp) { - struct dup_blks *b; + struct duptree *b; uint64_t i; uint8_t q; - osi_list_t *tmp = NULL, *x; + struct osi_node *n; struct metawalk_fxns find_dirents = {0}; int rc = FSCK_OK; find_dirents.check_dentry = &find_dentry; @@ -502,7 +494,7 @@ int pass1b(struct gfs2_sbd *sbp) log_info( _("Looking for duplicate blocks...\n")); /* If there were no dups in the bitmap, we don't need to do anymore */ - if(osi_list_empty(&dup_blocks.list)) { + if (dup_blocks.osi_node == NULL) { log_info( _("No duplicate blocks found\n")); return FSCK_OK; } @@ -526,9 +518,8 @@ int pass1b(struct gfs2_sbd *sbp) (q == gfs2_inode_chr) || (q == gfs2_inode_fifo) || (q == gfs2_inode_sock)) { - osi_list_foreach_safe(tmp, &dup_blocks.list, x) { - b = osi_list_entry(tmp, struct dup_blks, - list); + for (n = osi_first(&dup_blocks); n; n = osi_next(n)) { + b = (struct duptree *)n; if(find_block_ref(sbp, i, b)) { stack; rc = FSCK_ERROR; @@ -545,8 +536,8 @@ int pass1b(struct gfs2_sbd *sbp) * it later */ log_info( _("Handling duplicate blocks\n")); out: - osi_list_foreach_safe(tmp, &dup_blocks.list, x) { - b = osi_list_entry(tmp, struct dup_blks, list); + for (n = osi_first(&dup_blocks); n; n = osi_next(n)) { + b = (struct duptree *)n; if (!skip_this_pass && !rc) /* no error & not asked to skip the rest */ handle_dup_blk(sbp, b); /* Do not attempt to free the dup_blocks list or its parts diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c index 27a7cc7..90f6572 100644 --- a/gfs2/fsck/pass2.c +++ b/gfs2/fsck/pass2.c @@ -665,7 +665,6 @@ int pass2(struct gfs2_sbd *sbp) int filename_len; char tmp_name[256]; int error = 0; - struct dup_blks *b; /* Check all the system directory inodes. */ if (check_system_dir(sbp->md.jiinode, "jindex", build_jindex)) { @@ -811,12 +810,7 @@ int pass2(struct gfs2_sbd *sbp) deleting it from both inodes referencing it. Note: The other returns from this function are premature exits of the program and gfs2_block_list_destroy should get rid of the list for us. */ - while (!osi_list_empty(&dup_blocks.list)) { - b = osi_list_entry(dup_blocks.list.next, - struct dup_blks, list); - osi_list_del(&b->list); - free(b); - } + gfs2_dup_free(); return FSCK_OK; } diff --git a/gfs2/fsck/util.c b/gfs2/fsck/util.c index a705975..8a89d01 100644 --- a/gfs2/fsck/util.c +++ b/gfs2/fsck/util.c @@ -151,18 +151,49 @@ int fsck_query(const char *format, ...) return ret; } -void gfs2_dup_set(uint64_t block) +struct duptree *gfs2_dup_set(uint64_t dblock) { - struct dup_blks *b; + struct osi_node **newn = &dup_blocks.osi_node, *parent = NULL; + struct duptree *data; + + /* Figure out where to put new node */ + while (*newn) { + struct duptree *cur = (struct duptree *)*newn; + + parent = *newn; + if (dblock < cur->block) + newn = &((*newn)->osi_left); + else if (dblock > cur->block) + newn = &((*newn)->osi_right); + else + return cur; + } - if (dupfind(block)) - return; - b = malloc(sizeof(struct dup_blks)); - if (b) { - memset(b, 0, sizeof(*b)); - b->block = block; - osi_list_init(&b->ref_inode_list); - osi_list_add(&b->list, &dup_blocks.list); + data = malloc(sizeof(struct duptree)); + memset(data, 0, sizeof(struct duptree)); + /* Add new node and rebalance tree. */ + data->block = dblock; + data->refs = 2; /* first call is the second reference to the block */ + osi_list_init(&data->ref_inode_list); + osi_link_node(&data->node, parent, newn); + osi_insert_color(&data->node, &dup_blocks); + + return data; +} + +void dup_delete(struct duptree *b) +{ + struct inode_with_dups *id; + osi_list_t *tmp; + + while (!osi_list_empty(&b->ref_inode_list)) { + tmp = (&b->ref_inode_list)->next; + id = osi_list_entry(tmp, struct inode_with_dups, list); + if (id->name) + free(id->name); + osi_list_del(&id->list); + free(id); } - return; + osi_erase(&b->node, &dup_blocks); + free(b); } diff --git a/gfs2/fsck/util.h b/gfs2/fsck/util.h index e3ff7e3..3599b6b 100644 --- a/gfs2/fsck/util.h +++ b/gfs2/fsck/util.h @@ -11,7 +11,7 @@ struct di_info *search_list(osi_list_t *list, uint64_t addr); void big_file_comfort(struct gfs2_inode *ip, uint64_t blks_checked); void warm_fuzzy_stuff(uint64_t block); const char *block_type_string(uint8_t q); -void gfs2_dup_set(uint64_t block); +struct duptree *gfs2_dup_set(uint64_t dblock); static inline uint8_t block_type(uint64_t bblock) { diff --git a/gfs2/include/osi_tree.h b/gfs2/include/osi_tree.h new file mode 100644 index 0000000..4ffae94 --- /dev/null +++ b/gfs2/include/osi_tree.h @@ -0,0 +1,395 @@ +#ifndef __OSI_RBTREE_DOT_H__ +#define __OSI_RBTREE_DOT_H__ + +#include <stdlib.h> +#include <stddef.h> +#include <assert.h> + +/* Adapted from the kernel's rbtree.c */ +struct osi_node { + unsigned long osi_parent_color; +#define OSI_RED 0 +#define OSI_BLACK 1 + struct osi_node *osi_left; + struct osi_node *osi_right; + struct osi_node *osi_parent; +}; + +#define osi_parent(r) ((struct osi_node *)((r)->osi_parent_color & ~3)) +#define osi_color(r) ((r)->osi_parent_color & 1) +#define osi_is_red(r) (!osi_color(r)) +#define osi_is_black(r) osi_color(r) +#define osi_set_red(r) do { (r)->osi_parent_color &= ~1; } while (0) +#define osi_set_black(r) do { (r)->osi_parent_color |= 1; } while (0) + +struct osi_root +{ + struct osi_node *osi_node; +}; + +static inline void osi_set_color(struct osi_node *rb, int color) +{ + rb->osi_parent_color = (rb->osi_parent_color & ~1) | color; +} + +static inline void osi_set_parent(struct osi_node *rb, struct osi_node *p) +{ + rb->osi_parent_color = (rb->osi_parent_color & 3) | (unsigned long)p; +} + +static inline void osi_link_node(struct osi_node *node, + struct osi_node *parent, + struct osi_node **osi_link) +{ + node->osi_parent_color = (unsigned long )parent; + node->osi_left = node->osi_right = NULL; + + *osi_link = node; +} + +static inline void __osi_rotate_left(struct osi_node *node, + struct osi_root *root) +{ + struct osi_node *right = node->osi_right; + struct osi_node *parent = osi_parent(node); + + if ((node->osi_right = right->osi_left)) + osi_set_parent(right->osi_left, node); + right->osi_left = node; + + osi_set_parent(right, parent); + + if (parent) { + if (node == parent->osi_left) + parent->osi_left = right; + else + parent->osi_right = right; + } + else + root->osi_node = right; + osi_set_parent(node, right); +} + +static inline void __osi_rotate_right(struct osi_node *node, + struct osi_root *root) +{ + struct osi_node *left = node->osi_left; + struct osi_node *parent = osi_parent(node); + + if ((node->osi_left = left->osi_right)) + osi_set_parent(left->osi_right, node); + left->osi_right = node; + + osi_set_parent(left, parent); + + if (parent) { + if (node == parent->osi_right) + parent->osi_right = left; + else + parent->osi_left = left; + } else + root->osi_node = left; + osi_set_parent(node, left); +} + +static inline void osi_insert_color(struct osi_node *node, + struct osi_root *root) +{ + struct osi_node *parent, *gparent; + + while ((parent = osi_parent(node)) && osi_is_red(parent)) { + gparent = osi_parent(parent); + + if (parent == gparent->osi_left) { + { + register struct osi_node *uncle = gparent->osi_right; + if (uncle && osi_is_red(uncle)) { + osi_set_black(uncle); + osi_set_black(parent); + osi_set_red(gparent); + node = gparent; + continue; + } + } + + if (parent->osi_right == node) { + register struct osi_node *tmp; + + __osi_rotate_left(parent, root); + tmp = parent; + parent = node; + node = tmp; + } + + osi_set_black(parent); + osi_set_red(gparent); + __osi_rotate_right(gparent, root); + } else { + { + register struct osi_node *uncle = gparent->osi_left; + if (uncle && osi_is_red(uncle)) { + osi_set_black(uncle); + osi_set_black(parent); + osi_set_red(gparent); + node = gparent; + continue; + } + } + + if (parent->osi_left == node) { + register struct osi_node *tmp; + __osi_rotate_right(parent, root); + tmp = parent; + parent = node; + node = tmp; + } + + osi_set_black(parent); + osi_set_red(gparent); + __osi_rotate_left(gparent, root); + } + } + + osi_set_black(root->osi_node); +} + +static inline void __osi_erase_color(struct osi_node *node, + struct osi_node *parent, + struct osi_root *root) +{ + struct osi_node *other; + + while ((!node || osi_is_black(node)) && node != root->osi_node) { + if (parent->osi_left == node) { + other = parent->osi_right; + if (osi_is_red(other)) { + osi_set_black(other); + osi_set_red(parent); + __osi_rotate_left(parent, root); + other = parent->osi_right; + } + if ((!other->osi_left || osi_is_black(other->osi_left)) && + (!other->osi_right || osi_is_black(other->osi_right))) + { + osi_set_red(other); + node = parent; + parent = osi_parent(node); + } else { + if (!other->osi_right || osi_is_black(other->osi_right)) + { + struct osi_node *o_left; + if ((o_left = other->osi_left)) + osi_set_black(o_left); + osi_set_red(other); + __osi_rotate_right(other, root); + other = parent->osi_right; + } + osi_set_color(other, osi_color(parent)); + osi_set_black(parent); + if (other->osi_right) + osi_set_black(other->osi_right); + __osi_rotate_left(parent, root); + node = root->osi_node; + break; + } + } else { + other = parent->osi_left; + if (osi_is_red(other)) { + osi_set_black(other); + osi_set_red(parent); + __osi_rotate_right(parent, root); + other = parent->osi_left; + } + if ((!other->osi_left || osi_is_black(other->osi_left)) && + (!other->osi_right || osi_is_black(other->osi_right))) + { + osi_set_red(other); + node = parent; + parent = osi_parent(node); + } else { + if (!other->osi_left || osi_is_black(other->osi_left)) + { + register struct osi_node *o_right; + if ((o_right = other->osi_right)) + osi_set_black(o_right); + osi_set_red(other); + __osi_rotate_left(other, root); + other = parent->osi_left; + } + osi_set_color(other, osi_color(parent)); + osi_set_black(parent); + if (other->osi_left) + osi_set_black(other->osi_left); + __osi_rotate_right(parent, root); + node = root->osi_node; + break; + } + } + } + if (node) + osi_set_black(node); +} + +static inline void osi_erase(struct osi_node *node, struct osi_root *root) +{ + struct osi_node *child, *parent; + int color; + + if (!node->osi_left) + child = node->osi_right; + else if (!node->osi_right) + child = node->osi_left; + else { + struct osi_node *old = node, *left; + + node = node->osi_right; + while ((left = node->osi_left) != NULL) + node = left; + child = node->osi_right; + parent = osi_parent(node); + color = osi_color(node); + + if (child) + osi_set_parent(child, parent); + if (parent == old) { + parent->osi_right = child; + parent = node; + } else + parent->osi_left = child; + + node->osi_parent_color = old->osi_parent_color; + node->osi_right = old->osi_right; + node->osi_left = old->osi_left; + + if (osi_parent(old)) { + if (osi_parent(old)->osi_left == old) + osi_parent(old)->osi_left = node; + else + osi_parent(old)->osi_right = node; + } else + root->osi_node = node; + + osi_set_parent(old->osi_left, node); + if (old->osi_right) + osi_set_parent(old->osi_right, node); + goto color; + } + + parent = osi_parent(node); + color = osi_color(node); + + if (child) + osi_set_parent(child, parent); + if (parent) + { + if (parent->osi_left == node) + parent->osi_left = child; + else + parent->osi_right = child; + } + else + root->osi_node = child; + + color: + if (color == OSI_BLACK) + __osi_erase_color(child, parent, root); +} + +/* + * This function returns the first node (in sort order) of the tree. + */ +static inline struct osi_node *osi_first(struct osi_root *root) +{ + struct osi_node *n; + + n = root->osi_node; + if (!n) + return NULL; + while (n->osi_left) + n = n->osi_left; + return n; +} + +static inline struct osi_node *osi_last(struct osi_root *root) +{ + struct osi_node *n; + + n = root->osi_node; + if (!n) + return NULL; + while (n->osi_right) + n = n->osi_right; + return n; +} + +static inline struct osi_node *osi_next(struct osi_node *node) +{ + struct osi_node *parent; + + /* If we have a right-hand child, go down and then left as far + as we can. */ + if (node->osi_right) { + node = node->osi_right; + while (node->osi_left) + node=node->osi_left; + return node; + } + + /* No right-hand children. Everything down and left is + smaller than us, so any 'next' node must be in the general + direction of our parent. Go up the tree; any time the + ancestor is a right-hand child of its parent, keep going + up. First time it's a left-hand child of its parent, said + parent is our 'next' node. */ + while ((parent = osi_parent(node)) && node == parent->osi_right) + node = parent; + + return parent; +} + +static inline struct osi_node *osi_prev(struct osi_node *node) +{ + struct osi_node *parent; + + /* If we have a left-hand child, go down and then right as far + as we can. */ + if (node->osi_left) { + node = node->osi_left; + while (node->osi_right) + node=node->osi_right; + return node; + } + + /* No left-hand children. Go up till we find an ancestor which + is a right-hand child of its parent */ + while ((parent = osi_parent(node)) && node == parent->osi_left) + node = parent; + + return parent; +} + +static inline void osi_replace_node(struct osi_node *victim, + struct osi_node *new, + struct osi_root *root) +{ + struct osi_node *parent = osi_parent(victim); + + /* Set the surrounding nodes to point to the replacement */ + if (parent) { + if (victim == parent->osi_left) + parent->osi_left = new; + else + parent->osi_right = new; + } else { + root->osi_node = new; + } + if (victim->osi_left) + osi_set_parent(victim->osi_left, new); + if (victim->osi_right) + osi_set_parent(victim->osi_right, new); + + /* Copy the pointers/colour from the victim to the replacement */ + *new = *victim; +} + +#endif
1
0
0
0
cluster: STABLE3 - libgfs2: gfs2_log reform
by Bob Peterson
26 Jan '10
26 Jan '10
Gitweb:
http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=5b…
Commit: 5b7d0817560827d007b5ee0927a9dbb414aa1121 Parent: c0c86631cd56ee2f91295034a039685044fc11b7 Author: Bob Peterson <bob(a)ganesha.peterson> AuthorDate: Thu Jan 21 09:07:45 2010 -0600 Committer: Bob Peterson <rpeterso(a)redhat.com> CommitterDate: Tue Jan 26 14:39:29 2010 -0600 libgfs2: gfs2_log reform This patch reforms the log_ functions of libgfs2 to be a bit more efficient by getting rid of sub-structures and levels. rhbz#455300 --- gfs2/libgfs2/gfs2_log.c | 20 ++++++-------------- gfs2/libgfs2/libgfs2.h | 40 ++++++++++++---------------------------- 2 files changed, 18 insertions(+), 42 deletions(-) diff --git a/gfs2/libgfs2/gfs2_log.c b/gfs2/libgfs2/gfs2_log.c index 622589b..c349840 100644 --- a/gfs2/libgfs2/gfs2_log.c +++ b/gfs2/libgfs2/gfs2_log.c @@ -12,19 +12,16 @@ #define _(String) gettext(String) -struct log_state { - int print_level; -}; -static struct log_state _state = {MSG_NOTICE}; +int print_level = MSG_NOTICE; void increase_verbosity(void) { - _state.print_level++; + print_level++; } void decrease_verbosity(void) { - _state.print_level--; + print_level--; } static __attribute__((format (printf, 4, 0))) @@ -34,9 +31,8 @@ void print_msg(int priority, const char *file, int line, switch (priority) { case MSG_DEBUG: - printf("(%s:%d)\t", file, line); + printf("(%s:%d) ", file, line); vprintf(format, args); - fflush(NULL); break; case MSG_INFO: case MSG_NOTICE: @@ -53,7 +49,7 @@ void print_msg(int priority, const char *file, int line, } -void print_fsck_log(int iif, int priority, const char *file, int line, +void print_fsck_log(int priority, const char *file, int line, const char *format, ...) { va_list args; @@ -61,11 +57,7 @@ void print_fsck_log(int iif, int priority, const char *file, int line, va_start(args, format); transform = _(format); - - if((_state.print_level == priority) || - (!iif && (_state.print_level >= priority))) - print_msg(priority, file, line, transform, args); - + print_msg(priority, file, line, transform, args); va_end(args); } diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h index b0745aa..86db414 100644 --- a/gfs2/libgfs2/libgfs2.h +++ b/gfs2/libgfs2/libgfs2.h @@ -512,6 +512,8 @@ struct gfs2_options { unsigned int query:1; }; +extern int print_level; + #define MSG_DEBUG 7 #define MSG_INFO 6 #define MSG_NOTICE 5 @@ -520,52 +522,34 @@ struct gfs2_options { #define MSG_CRITICAL 2 #define MSG_NULL 1 -#define print_log(iif, priority, format...) \ -do { print_fsck_log(iif, priority, __FILE__, __LINE__, ## format); } while(0) +#define print_log(priority, format...) \ + do { print_fsck_log(priority, __FILE__, __LINE__, ## format); } while(0) #define log_debug(format...) \ -do { print_log(0, MSG_DEBUG, format); } while(0) + do { if(print_level >= MSG_DEBUG) print_log(MSG_DEBUG, format); } while(0) #define log_info(format...) \ -do { print_log(0, MSG_INFO, format); } while(0) + do { if(print_level >= MSG_INFO) print_log(MSG_INFO, format); } while(0) #define log_notice(format...) \ -do { print_log(0, MSG_NOTICE, format); } while(0) + do { if(print_level >= MSG_NOTICE) print_log(MSG_NOTICE, format); } while(0) #define log_warn(format...) \ -do { print_log(0, MSG_WARN, format); } while(0) + do { if(print_level >= MSG_WARN) print_log(MSG_WARN, format); } while(0) #define log_err(format...) \ -do { print_log(0, MSG_ERROR, format); } while(0) + do { if(print_level >= MSG_ERROR) print_log(MSG_ERROR, format); } while(0) #define log_crit(format...) \ -do { print_log(0, MSG_CRITICAL, format); } while(0) + do { if(print_level >= MSG_CRITICAL) print_log(MSG_CRITICAL, format); } while(0) #define stack log_debug("<backtrace> - %s()\n", __func__) -#define log_at_debug(format...) \ -do { print_log(1, MSG_DEBUG, format); } while(0) - -#define log_at_info(format...) \ -do { print_log(1, MSG_INFO, format); } while(0) - -#define log_at_notice(format...) \ -do { print_log(1, MSG_NOTICE, format); } while(0) - -#define log_at_warn(format...) \ -do { print_log(1, MSG_WARN, format); } while(0) - -#define log_at_err(format...) \ -do { print_log(1, MSG_ERROR, format); } while(0) - -#define log_at_crit(format...) \ -do { print_log(1, MSG_CRITICAL, format); } while(0) - extern char gfs2_getch(void); extern void increase_verbosity(void); extern void decrease_verbosity(void); -extern void print_fsck_log(int iif, int priority, const char *file, int line, +extern void print_fsck_log(int priority, const char *file, int line, const char *format, ...) - __attribute__((format(printf,5,6))); + __attribute__((format(printf,4,5))); extern char generic_interrupt(const char *caller, const char *where, const char *progress, const char *question, const char *answers);
1
0
0
0
cluster: STABLE3 - libgfs2: fs_bits speed up bitmap operations
by Bob Peterson
26 Jan '10
26 Jan '10
Gitweb:
http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=c0…
Commit: c0c86631cd56ee2f91295034a039685044fc11b7 Parent: 324588669d02c9a1e1d2fe3ba3b8edf11863721b Author: Bob Peterson <bob(a)ganesha.peterson> AuthorDate: Thu Jan 21 08:50:05 2010 -0600 Committer: Bob Peterson <rpeterso(a)redhat.com> CommitterDate: Tue Jan 26 14:39:28 2010 -0600 libgfs2: fs_bits speed up bitmap operations This patch incorporates a faster set of bitmap operations once used by the kernel code and currently used by GFS1. rhbz#455300 --- gfs2/libgfs2/fs_bits.c | 77 +++++++++++++++++++++++++++++++++++------------- 1 files changed, 56 insertions(+), 21 deletions(-) diff --git a/gfs2/libgfs2/fs_bits.c b/gfs2/libgfs2/fs_bits.c index e657aa5..c420dfc 100644 --- a/gfs2/libgfs2/fs_bits.c +++ b/gfs2/libgfs2/fs_bits.c @@ -5,6 +5,18 @@ #include "libgfs2.h" +#if BITS_PER_LONG == 32 +#define LBITMASK (0x55555555UL) +#define LBITSKIP55 (0x55555555UL) +#define LBITSKIP00 (0x00000000UL) +#else +#define LBITMASK (0x5555555555555555UL) +#define LBITSKIP55 (0x5555555555555555UL) +#define LBITSKIP00 (0x0000000000000000UL) +#endif + +#define ALIGN(x,a) (((x)+(a)-1)&~((a)-1)) + /** * gfs2_bitfit - Find a free block in the bitmaps * @buffer: the buffer that holds the bitmaps @@ -18,32 +30,55 @@ uint32_t gfs2_bitfit(unsigned char *buffer, unsigned int buflen, uint32_t goal, unsigned char old_state) { - unsigned char *byte, *end, alloc; - uint32_t blk = goal; - unsigned int bit; - - byte = buffer + (goal / GFS2_NBBY); - bit = (goal % GFS2_NBBY) * GFS2_BIT_SIZE; - end = buffer + buflen; - alloc = (old_state & 1) ? 0 : 0x55; - - while (byte < end){ - if ((*byte & 0x55) == alloc){ - blk += (8 - bit) >> 1; - bit = 0; - byte++; - continue; + const uint8_t *byte, *start, *end; + int bit, startbit; + uint32_t g1, g2, misaligned; + unsigned long *plong; + unsigned long lskipval; + + lskipval = (old_state & GFS2_BLKST_USED) ? LBITSKIP00 : LBITSKIP55; + g1 = (goal / GFS2_NBBY); + start = buffer + g1; + byte = start; + end = buffer + buflen; + g2 = ALIGN(g1, sizeof(unsigned long)); + plong = (unsigned long *)(buffer + g2); + startbit = bit = (goal % GFS2_NBBY) * GFS2_BIT_SIZE; + misaligned = g2 - g1; + if (!misaligned) + goto ulong_aligned; +/* parse the bitmap a byte at a time */ +misaligned: + while (byte < end) { + if (((*byte >> bit) & GFS2_BIT_MASK) == old_state) { + return goal + + (((byte - start) * GFS2_NBBY) + + ((bit - startbit) >> 1)); } - - if (((*byte >> bit) & GFS2_BIT_MASK) == old_state) - return blk; - bit += GFS2_BIT_SIZE; - if (bit >= 8){ + if (bit >= GFS2_NBBY * GFS2_BIT_SIZE) { bit = 0; byte++; + misaligned--; + if (!misaligned) { + plong = (unsigned long *)byte; + goto ulong_aligned; + } } - blk++; + } + return BFITNOENT; + +/* parse the bitmap a unsigned long at a time */ +ulong_aligned: + while ((unsigned char *)plong < end) { + if (((*plong) & LBITMASK) != lskipval) + break; + plong++; + } + if ((unsigned char *)plong < end) { + byte = (const uint8_t *)plong; + misaligned += sizeof(unsigned long) - 1; + goto misaligned; } return BFITNOENT; }
1
0
0
0
cluster: STABLE3 - gfs2: libgfs2 and fsck.gfs2 cleanups
by Bob Peterson
26 Jan '10
26 Jan '10
Gitweb:
http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=32…
Commit: 324588669d02c9a1e1d2fe3ba3b8edf11863721b Parent: 48cd85089a1a12d4c36fca20b9b3fed362b8f4b7 Author: Bob Peterson <bob(a)ganesha.peterson> AuthorDate: Wed Jan 20 15:46:50 2010 -0600 Committer: Bob Peterson <rpeterso(a)redhat.com> CommitterDate: Tue Jan 26 14:39:28 2010 -0600 gfs2: libgfs2 and fsck.gfs2 cleanups This patch is big, but mostly cosmetic. There are a few places where I found and fixed a bug with the previous patches. However, by and large, this patch is comprised of (1) comment changes, (2) code reformatting for readability, (3) variable renames to aid in readability, (4) code restructuring for efficiency, as in the case where I got rid of useless function scan_meta and just inlined it, (5) improved error messages given to aid in debugging. rhbz#455300 --- gfs2/convert/gfs2_convert.c | 5 +- gfs2/edit/gfs2hex.c | 3 +- gfs2/edit/hexedit.c | 2 +- gfs2/edit/savemeta.c | 11 ++-- gfs2/fsck/eattr.c | 8 +-- gfs2/fsck/fsck.h | 28 ++++---- gfs2/fsck/lost_n_found.c | 53 ++++----------- gfs2/fsck/metawalk.c | 48 +++++++------- gfs2/fsck/metawalk.h | 50 ++++++++------ gfs2/fsck/pass1.c | 97 ++++++++++++--------------- gfs2/fsck/pass1b.c | 33 +++++---- gfs2/fsck/pass1c.c | 1 - gfs2/fsck/pass2.c | 157 +++++++++++++++++++++++-------------------- gfs2/fsck/pass3.c | 13 ++-- gfs2/fsck/pass4.c | 21 +++--- gfs2/fsck/pass5.c | 8 +- gfs2/fsck/rgrepair.c | 10 ++-- gfs2/fsck/util.c | 4 +- gfs2/libgfs2/block_list.c | 1 - gfs2/libgfs2/buf.c | 4 +- gfs2/libgfs2/fs_ops.c | 71 +++++++++----------- gfs2/libgfs2/gfs2_log.c | 6 +-- gfs2/libgfs2/libgfs2.h | 5 +- gfs2/libgfs2/super.c | 2 +- 24 files changed, 307 insertions(+), 334 deletions(-) diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c index 2e10496..5d8d9cd 100644 --- a/gfs2/convert/gfs2_convert.c +++ b/gfs2/convert/gfs2_convert.c @@ -331,8 +331,7 @@ static void fix_metatree(struct gfs2_sbd *sbp, struct gfs2_inode *ip, if (amount > sbp->bsize - hdrsize - ptramt) amount = sbp->bsize - hdrsize - ptramt; - memcpy(bh->b_data + hdrsize + ptramt, - (char *)srcptr, amount); + memcpy(bh->b_data + hdrsize + ptramt, (char *)srcptr, amount); srcptr += amount; bmodified(bh); if (bh != ip->i_bh) @@ -784,7 +783,7 @@ static int fetch_inum(struct gfs2_sbd *sbp, uint64_t iblock, /* Returns: 0 on success, -1 on failure */ /* ------------------------------------------------------------------------- */ static int process_dirent_info(struct gfs2_inode *dip, struct gfs2_sbd *sbp, - struct gfs2_buffer_head *bh, int dir_entries) + struct gfs2_buffer_head *bh, int dir_entries) { int error; struct gfs2_dirent *dent; diff --git a/gfs2/edit/gfs2hex.c b/gfs2/edit/gfs2hex.c index cbf8dc0..00c4481 100644 --- a/gfs2/edit/gfs2hex.c +++ b/gfs2/edit/gfs2hex.c @@ -470,7 +470,8 @@ static void do_eattr_extended(struct gfs2_buffer_head *ebh) print_gfs2("Eattr Entries:"); eol(0); - for (x = sizeof(struct gfs2_meta_header); x < sbd.bsize; x += ea.ea_rec_len) + for (x = sizeof(struct gfs2_meta_header); x < sbd.bsize; + x += ea.ea_rec_len) { eol(0); gfs2_ea_header_in(&ea, ebh->b_data + x); diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c index 0017a60..45dfcc4 100644 --- a/gfs2/edit/hexedit.c +++ b/gfs2/edit/hexedit.c @@ -3042,7 +3042,7 @@ static void dump_journal(const char *journal) abs_block = jblock + jb; dummy_bh.b_data = j_bh->b_data; } else { - error = fsck_readi(j_inode, (void *)&jbuf, jb, + error = fsck_readi(j_inode, (void *)jbuf, jb, sbd.bsize, &abs_block); if (!error) /* end of file */ break; diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c index 4b49050..a69816f 100644 --- a/gfs2/edit/savemeta.c +++ b/gfs2/edit/savemeta.c @@ -852,17 +852,16 @@ static int restore_data(int fd, int in_fd, int printblocksonly) fprintf(stderr, "bad seek: %s from %s:" "%d: block %lld (0x%llx)\n", strerror(errno), __FUNCTION__, - __LINE__, (unsigned long long) - savedata->blk, - (unsigned long long) - savedata->blk); + __LINE__, + (unsigned long long)savedata->blk, + (unsigned long long)savedata->blk); exit(-1); } if (write(fd, savedata->buf, sbd.bsize) != sbd.bsize) { fprintf(stderr, "write error: %s from " "%s:%d: block %lld (0x%llx)\n", - strerror(errno), - __FUNCTION__, __LINE__, + strerror(errno), __FUNCTION__, + __LINE__, (unsigned long long)savedata->blk, (unsigned long long)savedata->blk); exit(-1); diff --git a/gfs2/fsck/eattr.c b/gfs2/fsck/eattr.c index a319500..6be4fa3 100644 --- a/gfs2/fsck/eattr.c +++ b/gfs2/fsck/eattr.c @@ -42,17 +42,12 @@ int clear_eattr_entry (struct gfs2_inode *ip, void *private) { struct gfs2_sbd *sdp = ip->i_sbd; - char ea_name[256]; 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 */ @@ -71,8 +66,7 @@ int clear_eattr_entry (struct gfs2_inode *ip, } else { log_debug( _(" Pointers Required: %d\n" " Pointers Reported: %d\n"), - max_ptrs, - ea_hdr->ea_num_ptrs); + max_ptrs, ea_hdr->ea_num_ptrs); } diff --git a/gfs2/fsck/fsck.h b/gfs2/fsck/fsck.h index a15bc33..7107678 100644 --- a/gfs2/fsck/fsck.h +++ b/gfs2/fsck/fsck.h @@ -61,7 +61,7 @@ enum rgindex_trust_level { /* how far can we trust our RG index? */ struct dup_blks { osi_list_t list; - uint64_t block_no; + uint64_t block; osi_list_t ref_inode_list; }; @@ -70,19 +70,21 @@ extern struct gfs2_inode *fsck_inode_get(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh); extern void fsck_inode_put(struct gfs2_inode **ip); -int initialize(struct gfs2_sbd *sbp, int force_check, int preen, - int *all_clean); -void destroy(struct gfs2_sbd *sbp); -int pass1(struct gfs2_sbd *sbp); -int pass1b(struct gfs2_sbd *sbp); -int pass1c(struct gfs2_sbd *sbp); -int pass2(struct gfs2_sbd *sbp); -int pass3(struct gfs2_sbd *sbp); -int pass4(struct gfs2_sbd *sbp); -int pass5(struct gfs2_sbd *sbp); -int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count); -int fsck_query(const char *format, ...) +extern int initialize(struct gfs2_sbd *sbp, int force_check, int preen, + int *all_clean); +extern void destroy(struct gfs2_sbd *sbp); +extern int pass1(struct gfs2_sbd *sbp); +extern int pass1b(struct gfs2_sbd *sbp); +extern int pass1c(struct gfs2_sbd *sbp); +extern int pass2(struct gfs2_sbd *sbp); +extern int pass3(struct gfs2_sbd *sbp); +extern int pass4(struct gfs2_sbd *sbp); +extern int pass5(struct gfs2_sbd *sbp); +extern int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count); +extern int fsck_query(const char *format, ...) __attribute__((format(printf,1,2))); +extern struct dir_info *dirtree_find(uint64_t block); +extern void dirtree_delete(struct dir_info *b); /* FIXME: Hack to get this going for pass2 - this should be pulled out * of pass1 and put somewhere else... */ diff --git a/gfs2/fsck/lost_n_found.c b/gfs2/fsck/lost_n_found.c index bc07d7b..25dec6c 100644 --- a/gfs2/fsck/lost_n_found.c +++ b/gfs2/fsck/lost_n_found.c @@ -25,8 +25,6 @@ */ int add_inode_to_lf(struct gfs2_inode *ip){ char tmp_name[256]; - char *filename; - int filename_len; __be32 inode_type; if(!lf_dip) { @@ -34,7 +32,8 @@ int add_inode_to_lf(struct gfs2_inode *ip){ log_info( _("Locating/Creating lost and found directory\n")); - lf_dip = createi(ip->i_sbd->md.rooti, "lost+found", S_IFDIR | 0700, 0); + lf_dip = createi(ip->i_sbd->md.rooti, "lost+found", + S_IFDIR | 0700, 0); q = block_type(lf_dip->i_di.di_num.no_addr); if(q != gfs2_inode_dir) { /* This is a new lost+found directory, so set its @@ -59,28 +58,16 @@ int add_inode_to_lf(struct gfs2_inode *ip){ } switch(ip->i_di.di_mode & S_IFMT){ case S_IFDIR: - log_info( _("Adding .. entry pointing to lost+found for %llu\n"), - (unsigned long long)ip->i_di.di_num.no_addr); - sprintf(tmp_name, ".."); - filename_len = strlen(tmp_name); /* no trailing NULL */ - if(!(filename = malloc((sizeof(char) * filename_len) + 1))) { - log_err( _("Unable to allocate name\n")); - stack; - return -1; - } - if(!memset(filename, 0, (sizeof(char) * filename_len) + 1)) { - log_err( _("Unable to zero name\n")); - stack; - return -1; - } - memcpy(filename, tmp_name, filename_len); + log_info( _("Adding .. entry pointing to lost+found for " + "directory %llu (0x%llx)\n"), + (unsigned long long)ip->i_di.di_num.no_addr, + (unsigned long long)ip->i_di.di_num.no_addr); - if(gfs2_dirent_del(ip, filename, filename_len)) - log_warn( _("add_inode_to_lf: " - "Unable to remove \"..\" directory entry.\n")); + if(gfs2_dirent_del(ip, "..", 2)) + log_warn( _("add_inode_to_lf: Unable to remove " + "\"..\" directory entry.\n")); - dir_add(ip, filename, filename_len, &(lf_dip->i_di.di_num), DT_DIR); - free(filename); + dir_add(ip, "..", 2, &(lf_dip->i_di.di_num), DT_DIR); sprintf(tmp_name, "lost_dir_%llu", (unsigned long long)ip->i_di.di_num.no_addr); inode_type = DT_DIR; @@ -121,26 +108,14 @@ int add_inode_to_lf(struct gfs2_inode *ip){ inode_type = DT_REG; break; } - filename_len = strlen(tmp_name); /* no trailing NULL */ - if(!(filename = malloc(sizeof(char) * filename_len))) { - log_err( _("Unable to allocate name\n")); - stack; - return -1; - } - if(!memset(filename, 0, sizeof(char) * filename_len)) { - log_err( _("Unable to zero name\n")); - stack; - return -1; - } - memcpy(filename, tmp_name, filename_len); - dir_add(lf_dip, filename, filename_len, &(ip->i_di.di_num), inode_type); - increment_link(ip->i_sbd, ip->i_di.di_num.no_addr); + dir_add(lf_dip, tmp_name, strlen(tmp_name), &(ip->i_di.di_num), + inode_type); + increment_link(ip->i_sbd, ip->i_di.di_num.no_addr); if(S_ISDIR(ip->i_di.di_mode)) increment_link(ip->i_sbd, lf_dip->i_di.di_num.no_addr); - free(filename); log_notice( _("Added inode #%llu 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); return 0; } diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c index d348123..6dd46cd 100644 --- a/gfs2/fsck/metawalk.c +++ b/gfs2/fsck/metawalk.c @@ -24,7 +24,7 @@ struct dup_blks *dupfind(uint64_t num) for (tmp = head->next; tmp != head; tmp = tmp->next) { b = osi_list_entry(tmp, struct dup_blks, list); - if (b->block_no == num) + if (b->block == num) return b; } return NULL; @@ -281,8 +281,7 @@ static int check_entries(struct gfs2_inode *ip, struct gfs2_buffer_head *bh, bmodified(bh); /* Mark dirent buffer as modified */ first = 0; - } - else { + } else { error = pass->check_dentry(ip, dent, prev, bh, filename, count, pass->private); @@ -294,7 +293,12 @@ static int check_entries(struct gfs2_inode *ip, struct gfs2_buffer_head *bh, } if ((char *)dent + de.de_rec_len >= bh_end){ - log_debug( _("Last entry processed.\n")); + log_debug( _("Last entry processed for %lld->%lld " + "(0x%llx->0x%llx).\n"), + (unsigned long long)ip->i_di.di_num.no_addr, + (unsigned long long)bh->b_blocknr, + (unsigned long long)ip->i_di.di_num.no_addr, + (unsigned long long)bh->b_blocknr); break; } @@ -387,8 +391,7 @@ static int check_leaf_blks(struct gfs2_inode *ip, struct metawalk_fxns *pass) leaf info */ ref_count++; continue; - } - else if(old_leaf == leaf_no) { + } else if(old_leaf == leaf_no) { ref_count++; continue; } @@ -490,11 +493,11 @@ static int check_leaf_blks(struct gfs2_inode *ip, struct metawalk_fxns *pass) break; } exp_count = (1 << (ip->i_di.di_depth - leaf.lf_depth)); - log_debug( _("expected count %u - di_depth %u, leaf depth %u\n"), - exp_count, ip->i_di.di_depth, leaf.lf_depth); + /*log_debug( _("expected count %u - di_depth %u, + leaf depth %u\n"), + exp_count, ip->i_di.di_depth, leaf.lf_depth);*/ - if(pass->check_dentry && - S_ISDIR(ip->i_di.di_mode)) { + if(pass->check_dentry && S_ISDIR(ip->i_di.di_mode)) { error = check_entries(ip, lbh, DIR_EXHASH, &count, pass); @@ -560,9 +563,8 @@ static int check_eattr_entries(struct gfs2_inode *ip, int error = 0; uint32_t offset = (uint32_t)sizeof(struct gfs2_meta_header); - if(!pass->check_eattr_entry) { + if(!pass->check_eattr_entry) return 0; - } ea_hdr = (struct gfs2_ea_header *)(bh->b_data + sizeof(struct gfs2_meta_header)); @@ -761,7 +763,7 @@ static int check_indirect_eattr(struct gfs2_inode *ip, uint64_t indirect, pass->private); } if (leaf_pointer_errors == leaf_pointers) { - if (indirect_buf->b_changed) + if (indirect_buf->b_modified) gfs2_set_bitmap(sdp, indirect, GFS2_BLKST_FREE); gfs2_blockmap_set(sdp, bl, indirect, @@ -794,8 +796,7 @@ int check_inode_eattr(struct gfs2_inode *ip, struct metawalk_fxns *pass) (unsigned long long)ip->i_di.di_num.no_addr); if(ip->i_di.di_flags & GFS2_DIF_EA_INDIRECT){ - if((error = check_indirect_eattr(ip, ip->i_di.di_eattr, - pass))) + if((error = check_indirect_eattr(ip, ip->i_di.di_eattr, pass))) stack; } else { error = check_leaf_eattr(ip, ip->i_di.di_eattr, @@ -809,12 +810,13 @@ int check_inode_eattr(struct gfs2_inode *ip, struct metawalk_fxns *pass) /** * build_and_check_metalist - check a bunch of indirect blocks - * Note: Every buffer put on the metalist should be "held". + * This includes hash table blocks for directories + * which are technically "data" in the bitmap. + * * @ip: * @mlp: */ -static int build_and_check_metalist(struct gfs2_inode *ip, - osi_list_t *mlp, +static int build_and_check_metalist(struct gfs2_inode *ip, osi_list_t *mlp, struct metawalk_fxns *pass) { uint32_t height = ip->i_di.di_height; @@ -829,7 +831,7 @@ static int build_and_check_metalist(struct gfs2_inode *ip, /* if(<there are no indirect blocks to check>) */ if (height < 2) return 0; - for (i = 1; i < height; i++){ + for (i = 1; i < height; i++) { prev_list = &mlp[i - 1]; cur_list = &mlp[i]; @@ -848,7 +850,7 @@ static int build_and_check_metalist(struct gfs2_inode *ip, continue; head_size = sizeof(struct gfs2_dinode); } - + /* Now check the metadata itself */ for (ptr = (uint64_t *)(bh->b_data + head_size); (char *)ptr < (bh->b_data + ip->i_sbd->bsize); ptr++) { @@ -982,7 +984,6 @@ int check_metatree(struct gfs2_inode *ip, struct metawalk_fxns *pass) big_file_comfort(ip, blks_checked); } } - if (ip->i_di.di_blocks > COMFORTABLE_BLKS) { log_notice( _("\rLarge file at %lld (0x%llx) - 100 percent " "complete. " @@ -1024,8 +1025,8 @@ end: } /* Checks stuffed inode directories */ -static int check_linear_dir(struct gfs2_inode *ip, struct gfs2_buffer_head *bh, - struct metawalk_fxns *pass) +int check_linear_dir(struct gfs2_inode *ip, struct gfs2_buffer_head *bh, + struct metawalk_fxns *pass) { int error = 0; uint16_t count = 0; @@ -1039,7 +1040,6 @@ static int check_linear_dir(struct gfs2_inode *ip, struct gfs2_buffer_head *bh, return error; } - int check_dir(struct gfs2_sbd *sbp, uint64_t block, struct metawalk_fxns *pass) { struct gfs2_inode *ip; diff --git a/gfs2/fsck/metawalk.h b/gfs2/fsck/metawalk.h index 0ad0aa2..c24c705 100644 --- a/gfs2/fsck/metawalk.h +++ b/gfs2/fsck/metawalk.h @@ -6,26 +6,33 @@ struct metawalk_fxns; -int check_inode_eattr(struct gfs2_inode *ip, struct metawalk_fxns *pass); -int check_metatree(struct gfs2_inode *ip, struct metawalk_fxns *pass); -int check_dir(struct gfs2_sbd *sbp, uint64_t block, - struct metawalk_fxns *pass); -int remove_dentry_from_dir(struct gfs2_sbd *sbp, uint64_t dir, - uint64_t dentryblock); -int find_di(struct gfs2_sbd *sbp, uint64_t childblock, struct dir_info **dip); -int dinode_hash_insert(osi_list_t *buckets, uint64_t key, struct dir_info *di); -int dinode_hash_remove(osi_list_t *buckets, uint64_t key); -int delete_blocks(struct gfs2_inode *ip, uint64_t block, - struct gfs2_buffer_head **bh, const char *btype, - void *private); -int delete_metadata(struct gfs2_inode *ip, uint64_t block, - struct gfs2_buffer_head **bh, void *private); -int delete_data(struct gfs2_inode *ip, uint64_t block, void *private); -int delete_eattr_indir(struct gfs2_inode *ip, uint64_t block, uint64_t parent, - struct gfs2_buffer_head **bh, void *private); -int delete_eattr_leaf(struct gfs2_inode *ip, uint64_t block, uint64_t parent, - struct gfs2_buffer_head **bh, void *private); -struct dup_blks *dupfind(uint64_t num); +extern int check_inode_eattr(struct gfs2_inode *ip, + struct metawalk_fxns *pass); +extern int check_metatree(struct gfs2_inode *ip, struct metawalk_fxns *pass); +extern int check_dir(struct gfs2_sbd *sbp, uint64_t block, + struct metawalk_fxns *pass); +extern int check_linear_dir(struct gfs2_inode *ip, struct gfs2_buffer_head *bh, + struct metawalk_fxns *pass); +extern int remove_dentry_from_dir(struct gfs2_sbd *sbp, uint64_t dir, + uint64_t dentryblock); +extern int find_di(struct gfs2_sbd *sbp, uint64_t childblock, + struct dir_info **dip); +extern int dinode_hash_insert(osi_list_t *buckets, uint64_t key, + struct dir_info *di); +extern int dinode_hash_remove(osi_list_t *buckets, uint64_t key); +extern int delete_blocks(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, void *private); +extern int delete_data(struct gfs2_inode *ip, uint64_t block, void *private); +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 struct dup_blks *dupfind(uint64_t num); #define is_duplicate(dblock) ((dupfind(dblock)) ? 1 : 0) @@ -74,8 +81,7 @@ struct metawalk_fxns { struct gfs2_ea_header *ea_hdr_prev, void *private); int (*finish_eattr_indir) (struct gfs2_inode *ip, int leaf_pointers, - int leaf_pointer_errors, - void *private); + int leaf_pointer_errors, void *private); }; #endif /* _METAWALK_H */ diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c index 2d1aed5..6862f29 100644 --- a/gfs2/fsck/pass1.c +++ b/gfs2/fsck/pass1.c @@ -73,8 +73,11 @@ static int leaf(struct gfs2_inode *ip, uint64_t block, { struct block_count *bc = (struct block_count *) private; - log_debug( _("\tLeaf block at %15" PRIu64 " (0x%" PRIx64 ")\n"), - block, block); + log_debug( _("\tDinode %lld (0x%llx) references leaf block #%lld " + "(0x%llx)\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); gfs2_blockmap_set(ip->i_sbd, bl, block, gfs2_leaf_blk); bc->indir_count++; return 0; @@ -148,7 +151,7 @@ static int check_data(struct gfs2_inode *ip, uint64_t block, void *private) return 1; } q = block_type(block); - if(q != gfs2_block_free) { + if (q != gfs2_block_free) { log_err( _("Found duplicate block referenced as data at %" PRIu64 " (0x%"PRIx64 ")\n"), block, block); if (q != gfs2_meta_inval) { @@ -234,8 +237,7 @@ static int ask_remove_inode_eattr(struct gfs2_inode *ip, 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); - if (query( _("Clear all Extended Attributes from the " - "inode? (y/n) "))) { + if (query( _("Clear all Extended Attributes from the inode? (y/n) "))){ if (!remove_inode_eattr(ip, bc, is_duplicate(ip->i_di.di_eattr))) log_err( _("Extended attributes were removed.\n")); @@ -766,14 +768,14 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh, } pass1_fxns.private = &bc; - error = check_metatree(ip, &pass1_fxns); if (fsck_abort || error < 0) { fsck_inode_put(&ip); return 0; } - if(error > 0) { - log_warn( _("Marking inode #%llu (0x%llx) invalid\n"), + if (error > 0) { + log_err( _("Error: inode %llu (0x%llx) has unrecoverable " + "errors; invalidating.\n"), (unsigned long long)ip->i_di.di_num.no_addr, (unsigned long long)ip->i_di.di_num.no_addr); /* FIXME: Must set all leaves invalid as well */ @@ -810,7 +812,9 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh, ip->i_di.di_blocks = 1 + bc.indir_count + bc.data_count + bc.ea_count; bmodified(ip->i_bh); - gfs2_dinode_out(&ip->i_di, ip->i_bh); + log_err( _("Block count for #%llu (0x%llx) fixed\n"), + (unsigned long long)ip->i_di.di_num.no_addr, + (unsigned long long)ip->i_di.di_num.no_addr); } else log_err( _("Bad block count for #%llu (0x%llx" ") not fixed\n"), @@ -822,46 +826,6 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh, return 0; } -static int scan_meta(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh, - uint64_t block) -{ - if (gfs2_check_meta(bh, 0)) { - log_info( _("Found invalid metadata at #%llu (0x%llx)\n"), - (unsigned long long)block, - (unsigned long long)block); - if(gfs2_blockmap_set(sdp, bl, block, gfs2_meta_inval)) { - stack; - return -1; - } - if(query( _("Okay to free the invalid block? (y/n)"))) { - gfs2_set_bitmap(sdp, block, GFS2_BLKST_FREE); - log_err( _("The invalid block was freed.\n")); - } else { - log_err( _("The invalid block was ignored.\n")); - } - return 0; - } - - log_debug( _("Checking metadata block #%" PRIu64 " (0x%" PRIx64 ")\n"), block, - block); - - if (!gfs2_check_meta(bh, GFS2_METATYPE_DI)) { - /* handle_di calls inode_get, then inode_put, which does brelse. */ - /* In order to prevent brelse from getting the count off, hold it. */ - if(handle_di(sdp, bh, block)) { - stack; - return -1; - } - } - /* Ignore everything else - they should be hit by the handle_di step. - * Don't check NONE either, because check_meta passes everything if - * GFS2_METATYPE_NONE is specified. - * Hopefully, other metadata types such as indirect blocks will be - * handled when the inode itself is processed, and if it's not, it - * should be caught in pass5. */ - return 0; -} - /** * pass1 - walk through inodes and check inode state * @@ -902,10 +866,9 @@ int pass1(struct gfs2_sbd *sbp) * uses the rg bitmaps, so maybe that's the best way to start * things - we can change the method later if necessary. */ - for (tmp = sbp->rglist.next; tmp != &sbp->rglist; - tmp = tmp->next, rg_count++){ - log_info( _("Checking metadata in Resource Group #%" PRIu64 "\n"), + tmp = tmp->next, rg_count++) { + log_debug( _("Checking metadata in Resource Group #%" PRIu64 "\n"), rg_count); rgd = osi_list_entry(tmp, struct rgrp_list, list); for (i = 0; i < rgd->ri.ri_length; i++) { @@ -922,9 +885,12 @@ int pass1(struct gfs2_sbd *sbp) while (1) { /* "block" is relative to the entire file system */ + /* Get the next dinode in the file system, according + to the bitmap. This should ONLY be dinodes. */ if (gfs2_next_rg_meta(rgd, &block, first)) break; warm_fuzzy_stuff(block); + if (fsck_abort) /* if asked to abort */ return FSCK_OK; if (skip_this_pass) { @@ -934,11 +900,36 @@ int pass1(struct gfs2_sbd *sbp) } bh = bread(sbp, block); - if (scan_meta(sbp, bh, block)) { + /*log_debug( _("Checking metadata block #%" PRIu64 + " (0x%" PRIx64 ")\n"), block, block);*/ + + if (gfs2_check_meta(bh, GFS2_METATYPE_DI)) { + log_err( _("Found invalid inode at block #" + "%llu (0x%llx)\n"), + (unsigned long long)block, + (unsigned long long)block); + if(query( _("Okay to free the invalid block? " + "(y/n)"))) { + gfs2_set_bitmap(sbp, block, + GFS2_BLKST_FREE); + log_err( _("The invalid block was " + "freed.\n")); + } else { + log_err( _("The invalid block was " + "ignored.\n")); + } + } else if (handle_di(sbp, bh, block) < 0) { stack; brelse(bh); return FSCK_ERROR; } + /* Ignore everything else - they should be hit by the + handle_di step. Don't check NONE either, because + check_meta passes everything if GFS2_METATYPE_NONE + is specified. Hopefully, other metadata types such + as indirect blocks will be handled when the inode + itself is processed, and if it's not, it should be + caught in pass5. */ brelse(bh); first = 0; } diff --git a/gfs2/fsck/pass1b.c b/gfs2/fsck/pass1b.c index 4827534..ead608a 100644 --- a/gfs2/fsck/pass1b.c +++ b/gfs2/fsck/pass1b.c @@ -161,7 +161,7 @@ static int clear_dup_metalist(struct gfs2_inode *ip, uint64_t block, if(dh->ref_count == 1) return 1; - if(block == dh->b->block_no) { + if(block == dh->b->block) { log_err( _("Found duplicate reference in inode \"%s\" at " "block #%llu (0x%llx) to block #%llu (0x%llx)\n"), dh->id->name ? dh->id->name : _("unknown name"), @@ -195,7 +195,7 @@ static int clear_dup_eattr_indir(struct gfs2_inode *ip, uint64_t block, *bh = NULL; if(dh->ref_count == 1) return 1; - if(block == dh->b->block_no) { + if(block == dh->b->block) { log_err( _("Found dup in inode \"%s\" with address #%llu" " (0x%llx) with block #%llu (0x%llx)\n"), dh->id->name ? dh->id->name : _("unknown name"), @@ -221,7 +221,7 @@ static int clear_dup_eattr_leaf(struct gfs2_inode *ip, uint64_t block, if(dh->ref_count == 1) return 1; - if(block == dh->b->block_no) { + if(block == dh->b->block) { log_err( _("Found dup in inode \"%s\" with address #%llu" " (0x%llx) with block #%llu (0x%llx)\n"), dh->id->name ? dh->id->name : _("unknown name"), @@ -293,7 +293,7 @@ static int clear_eattr_extentry(struct gfs2_inode *ip, uint64_t *ea_data_ptr, if(dh->ref_count == 1) return 1; - if(block == dh->b->block_no) { + if(block == dh->b->block) { log_err( _("Found dup in inode \"%s\" with address #%llu" " (0x%llx) with block #%llu (0x%llx)\n"), dh->id->name ? dh->id->name : _("unknown name"), @@ -316,7 +316,7 @@ static int clear_eattr_extentry(struct gfs2_inode *ip, uint64_t *ea_data_ptr, static int find_block_ref(struct gfs2_sbd *sbp, uint64_t inode, struct dup_blks *b) { struct gfs2_inode *ip; - struct fxn_info myfi = {b->block_no, 0, 1}; + struct fxn_info myfi = {b->block, 0, 1}; struct inode_with_dups *id = NULL; struct metawalk_fxns find_refs = { .private = (void*) &myfi, @@ -333,7 +333,7 @@ static int find_block_ref(struct gfs2_sbd *sbp, uint64_t inode, struct dup_blks ip = fsck_load_inode(sbp, inode); /* bread, inode_get */ log_debug( _("Checking inode %" PRIu64 " (0x%" PRIx64 ")'s " "metatree for references to block %" PRIu64 " (0x%" PRIx64 - ")\n"), inode, inode, b->block_no, b->block_no); + ")\n"), inode, inode, b->block, b->block); if(check_metatree(ip, &find_refs)) { stack; fsck_inode_put(&ip); /* out, brelse, free */ @@ -357,7 +357,7 @@ static int find_block_ref(struct gfs2_sbd *sbp, uint64_t inode, struct dup_blks } log_debug( _("Found %d entries with block %" PRIu64 " (0x%" PRIx64 ") in inode #%" PRIu64 " (0x%" PRIx64 ")\n"), - myfi.found, b->block_no, b->block_no, inode, inode); + myfi.found, b->block, b->block, inode, inode); id->dup_count = myfi.found; id->block_no = inode; id->ea_only = myfi.ea_only; @@ -402,7 +402,7 @@ static int handle_dup_blk(struct gfs2_sbd *sbp, struct dup_blks *b) struct gfs2_buffer_head *bh; uint32_t cmagic; - bh = bread(sbp, b->block_no); + bh = bread(sbp, b->block); cmagic = ((struct gfs2_meta_header *)(bh->b_data))->mh_magic; brelse(bh); if (be32_to_cpu(cmagic) == GFS2_MAGIC) { @@ -413,8 +413,8 @@ static int handle_dup_blk(struct gfs2_sbd *sbp, struct dup_blks *b) "but the block is really metadata.\n"), id->name, (unsigned long long)id->block_no, (unsigned long long)id->block_no, - (unsigned long long)b->block_no, - (unsigned long long)b->block_no); + (unsigned long long)b->block, + (unsigned long long)b->block); if (query( _("Clear the inode? (y/n) "))) { log_warn( _("Clearing inode %lld (0x%llx)...\n"), (unsigned long long)id->block_no, @@ -438,8 +438,7 @@ static int handle_dup_blk(struct gfs2_sbd *sbp, struct dup_blks *b) log_notice( _("Block %llu (0x%llx) has %d inodes referencing it" " for a total of %d duplicate references\n"), - (unsigned long long)b->block_no, - (unsigned long long)b->block_no, + (unsigned long long)b->block, (unsigned long long)b->block, dh.ref_inode_count, dh.ref_count); osi_list_foreach(tmp, &b->ref_inode_list) { @@ -448,8 +447,8 @@ static int handle_dup_blk(struct gfs2_sbd *sbp, struct dup_blks *b) "block %llu (0x%llx)\n"), id->name, (unsigned long long)id->block_no, (unsigned long long)id->block_no, - id->dup_count, (unsigned long long)b->block_no, - (unsigned long long)b->block_no); + id->dup_count, (unsigned long long)b->block, + (unsigned long long)b->block); } osi_list_foreach(tmp, &b->ref_inode_list) { id = osi_list_entry(tmp, struct inode_with_dups, list); @@ -550,6 +549,12 @@ out: b = osi_list_entry(tmp, struct dup_blks, list); if (!skip_this_pass && !rc) /* no error & not asked to skip the rest */ handle_dup_blk(sbp, b); + /* Do not attempt to free the dup_blocks list or its parts + here because any func that calls check_metatree needs + to check duplicate status based on this linked list. + This is especially true for pass2 where it may delete "bad" + inodes, and we can't delete an inode's indirect block if + it was a duplicate (therefore in use by another dinode). */ } return rc; } diff --git a/gfs2/fsck/pass1c.c b/gfs2/fsck/pass1c.c index 4174363..10b92ed 100644 --- a/gfs2/fsck/pass1c.c +++ b/gfs2/fsck/pass1c.c @@ -206,7 +206,6 @@ static int check_eattr_extentry(struct gfs2_inode *ip, uint64_t *ea_ptr, uint8_t q; struct gfs2_sbd *sbp = ip->i_sbd; - q = block_type(be64_to_cpu(*ea_ptr)); if(q != gfs2_meta_eattr) { if(remove_eattr_entry(sbp, leaf_bh, ea_hdr, ea_hdr_prev)){ diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c index 5e60b50..27a7cc7 100644 --- a/gfs2/fsck/pass2.c +++ b/gfs2/fsck/pass2.c @@ -19,7 +19,7 @@ /* Set children's parent inode in dir_info structure - ext2 does not set * dotdot inode here, but instead in pass3 - should we? */ static int set_parent_dir(struct gfs2_sbd *sbp, uint64_t childblock, - uint64_t parentblock) + uint64_t parentblock) { struct dir_info *di; @@ -37,7 +37,7 @@ static int set_parent_dir(struct gfs2_sbd *sbp, uint64_t childblock, } } else { log_err( _("Unable to find block %"PRIu64" (0x%" PRIx64 - ") in dir_info list\n"), childblock, childblock); + ") in dir_info list\n"), childblock, childblock); return -1; } @@ -93,9 +93,9 @@ static int check_eattr_leaf(struct gfs2_inode *ip, uint64_t block, static const char *de_type_string(uint8_t de_type) { const char *de_types[15] = {"unknown", "fifo", "chrdev", "invalid", - "directory", "invalid", "blkdev", "invalid", - "file", "invalid", "symlink", "invalid", - "socket", "invalid", "wht"}; + "directory", "invalid", "blkdev", "invalid", + "file", "invalid", "symlink", "invalid", + "socket", "invalid", "wht"}; if (de_type < 15) return de_types[de_type]; return de_types[3]; /* invalid */ @@ -220,8 +220,10 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, strncpy(tmp_name, filename, MAX_FILENAME - 1); if(gfs2_check_range(ip->i_sbd, entryblock)) { - log_err( _("Block # referenced by directory entry %s is out of range\n"), - tmp_name); + log_err( _("Block # referenced by directory entry %s in inode " + "%lld (0x%llx) is out of range\n"), + tmp_name, (unsigned long long)ip->i_di.di_num.no_addr, + (unsigned long long)ip->i_di.di_num.no_addr); if(query( _("Clear directory entry tp out of range block? (y/n) "))) { log_err( _("Clearing %s\n"), tmp_name); dirent2_del(ip, bh, prev_de, dent); @@ -231,10 +233,12 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, log_err( _("Directory entry to out of range block remains\n")); (*count)++; ds->entry_count++; + /* can't do this because the block is out of range: + increment_link(entryblock); */ return 0; } } - q = block_type(de->de_inum.no_addr); + q = block_type(entryblock); /* Get the status of the directory inode */ if(q == gfs2_bad_block) { /* This entry's inode has bad blocks in it */ @@ -243,14 +247,13 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, log_err( _("Found a bad directory entry: %s\n"), filename); if(query( _("Delete inode containing bad blocks? (y/n)"))) { - entry_ip = fsck_load_inode(sbp, de->de_inum.no_addr); + entry_ip = fsck_load_inode(sbp, entryblock); check_inode_eattr(entry_ip, &pass2_fxns_delete); check_metatree(entry_ip, &pass2_fxns_delete); bmodified(entry_ip->i_bh); fsck_inode_put(&entry_ip); dirent2_del(ip, bh, prev_de, dent); - gfs2_blockmap_set(sbp, bl, de->de_inum.no_addr, - gfs2_block_free); + gfs2_blockmap_set(sbp, bl, entryblock, gfs2_block_free); bmodified(bh); log_warn( _("The inode containing bad blocks was " "deleted.\n")); @@ -263,15 +266,12 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, } } - if(q != gfs2_inode_dir && q != gfs2_inode_file && - q != gfs2_inode_lnk && q != gfs2_inode_blk && - q != gfs2_inode_chr && q != gfs2_inode_fifo && - q != gfs2_inode_sock) { - log_err( _("Directory entry '%s' at block %llu (0x%llx" - ") in dir inode %llu (0x%llx" - ") block type %d: %s.\n"), tmp_name, - (unsigned long long)de->de_inum.no_addr, - (unsigned long long)de->de_inum.no_addr, + if(q < gfs2_inode_dir || q > gfs2_inode_sock) { + log_err( _("Directory entry '%s' referencing inode %llu " + "(0x%llx) in dir inode %llu (0x%llx) block type " + "%d: %s.\n"), tmp_name, + (unsigned long long)entryblock, + (unsigned long long)entryblock, (unsigned long long)ip->i_di.di_num.no_addr, (unsigned long long)ip->i_di.di_num.no_addr, q, q == gfs2_meta_inval ? @@ -292,20 +292,19 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, return 1; /* Now try to clear the dinode, if it is an dinode */ - bhi = bread(sbp, de->de_inum.no_addr); + bhi = bread(sbp, entryblock); error = gfs2_check_meta(bhi, GFS2_METATYPE_DI); bmodified(bhi); brelse(bhi); if (error) return 1; /* not a dinode: nothing to delete */ - entry_ip = fsck_load_inode(sbp, de->de_inum.no_addr); + entry_ip = fsck_load_inode(sbp, entryblock); check_inode_eattr(entry_ip, &pass2_fxns_delete); check_metatree(entry_ip, &pass2_fxns_delete); bmodified(entry_ip->i_bh); fsck_inode_put(&entry_ip); - gfs2_blockmap_set(sbp, bl, de->de_inum.no_addr, - gfs2_block_free); + gfs2_blockmap_set(sbp, bl, entryblock, gfs2_block_free); return 1; } else { @@ -318,19 +317,29 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, error = check_file_type(de->de_type, q); if(error < 0) { + log_err( _("Error: directory entry type is " + "incompatible with block type at block %lld " + "(0x%llx) in directory inode %llu (0x%llx).\n"), + (unsigned long long)entryblock, + (unsigned long long)entryblock, + (unsigned long long)ip->i_di.di_num.no_addr, + (unsigned long long)ip->i_di.di_num.no_addr); + log_err( _("Directory entry type is %d, block type is %d.\n"), + de->de_type, q); stack; return -1; } if(error > 0) { - log_warn( _("Type '%s' in dir entry (%s, %llu/0x%llx) conflicts" + log_err( _("Type '%s' in dir entry (%s, %llu/0x%llx) conflicts" " with type '%s' in dinode. (Dir entry is stale.)\n"), de_type_string(de->de_type), tmp_name, - (unsigned long long)de->de_inum.no_addr, - (unsigned long long)de->de_inum.no_addr, + (unsigned long long)entryblock, + (unsigned long long)entryblock, block_type_string(q)); if(query( _("Clear stale directory entry? (y/n) "))) { - entry_ip = fsck_load_inode(sbp, de->de_inum.no_addr); - check_inode_eattr(entry_ip, &clear_eattrs); + entry_ip = fsck_load_inode(sbp, entryblock); + check_inode_eattr(entry_ip, &clear_eattrs); + if (entry_ip != ip) fsck_inode_put(&entry_ip); dirent2_del(ip, bh, prev_de, dent); @@ -354,7 +363,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, (unsigned long long)ip->i_di.di_num.no_addr, (unsigned long long)ip->i_di.di_num.no_addr); if(query( _("Clear duplicate '.' entry? (y/n) "))) { - entry_ip = fsck_load_inode(sbp, de->de_inum.no_addr); + entry_ip = fsck_load_inode(sbp, entryblock); check_inode_eattr(entry_ip, &clear_eattrs); fsck_inode_put(&entry_ip); @@ -366,7 +375,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, /* FIXME: Should we continue on here * and check the rest of the '.' * entry? */ - increment_link(sbp, de->de_inum.no_addr); + increment_link(sbp, entryblock); (*count)++; ds->entry_count++; return 0; @@ -377,19 +386,19 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, * location */ /* check that '.' refers to this inode */ - if(de->de_inum.no_addr != ip->i_di.di_num.no_addr) { + if(entryblock != ip->i_di.di_num.no_addr) { log_err( _("'.' entry's value incorrect in directory %llu" " (0x%llx). Points to %llu" " (0x%llx) when it should point to %llu" " (0x%llx).\n"), - (unsigned long long)de->de_inum.no_addr, - (unsigned long long)de->de_inum.no_addr, - (unsigned long long)de->de_inum.no_addr, - (unsigned long long)de->de_inum.no_addr, + (unsigned long long)entryblock, + (unsigned long long)entryblock, + (unsigned long long)entryblock, + (unsigned long long)entryblock, (unsigned long long)ip->i_di.di_num.no_addr, (unsigned long long)ip->i_di.di_num.no_addr); if(query( _("Remove '.' reference? (y/n) "))) { - entry_ip = fsck_load_inode(sbp, de->de_inum.no_addr); + entry_ip = fsck_load_inode(sbp, entryblock); check_inode_eattr(entry_ip, &clear_eattrs); fsck_inode_put(&entry_ip); @@ -401,7 +410,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, log_err( _("Invalid '.' reference remains\n")); /* Not setting ds->dotdir here since * this '.' entry is invalid */ - increment_link(sbp, de->de_inum.no_addr); + increment_link(sbp, entryblock); (*count)++; ds->entry_count++; return 0; @@ -409,7 +418,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, } ds->dotdir = 1; - increment_link(sbp, de->de_inum.no_addr); + increment_link(sbp, entryblock); (*count)++; ds->entry_count++; @@ -424,7 +433,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, (unsigned long long)ip->i_di.di_num.no_addr); if(query( _("Clear duplicate '..' entry? (y/n) "))) { - entry_ip = fsck_load_inode(sbp, de->de_inum.no_addr); + entry_ip = fsck_load_inode(sbp, entryblock); check_inode_eattr(entry_ip, &clear_eattrs); fsck_inode_put(&entry_ip); @@ -436,7 +445,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, /* FIXME: Should we continue on here * and check the rest of the '..' * entry? */ - increment_link(sbp, de->de_inum.no_addr); + increment_link(sbp, entryblock); (*count)++; ds->entry_count++; return 0; @@ -449,8 +458,9 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, (unsigned long long)ip->i_di.di_num.no_addr, (unsigned long long)ip->i_di.di_num.no_addr); if(query( _("Clear bad '..' directory entry? (y/n) "))) { - entry_ip = fsck_load_inode(sbp, de->de_inum.no_addr); - check_inode_eattr(entry_ip, &clear_eattrs); + entry_ip = fsck_load_inode(sbp, entryblock); + check_inode_eattr(entry_ip, &clear_eattrs); + if (entry_ip != ip) fsck_inode_put(&entry_ip); dirent2_del(ip, bh, prev_de, dent); @@ -458,14 +468,13 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, return 1; } else { log_err( _("Bad '..' directory entry remains\n")); - increment_link(sbp, de->de_inum.no_addr); + increment_link(sbp, entryblock); (*count)++; ds->entry_count++; return 0; } } - /* GFS2 does not rely on '..' being in a - * certain location */ + /* GFS2 does not rely on '..' being in a certain location */ /* Add the address this entry is pointing to * to this inode's dotdot_parent in @@ -476,27 +485,26 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, } ds->dotdotdir = 1; - increment_link(sbp, de->de_inum.no_addr); + increment_link(sbp, entryblock); (*count)++; ds->entry_count++; return 0; } - /* After this point we're only concerned with - * directories */ + /* After this point we're only concerned with directories */ if(q != gfs2_inode_dir) { log_debug( _("Found non-dir inode dentry\n")); - increment_link(sbp, de->de_inum.no_addr); + increment_link(sbp, entryblock); (*count)++; ds->entry_count++; return 0; } - log_debug( _("Found plain directory dentry\n")); + /*log_debug( _("Found plain directory dentry\n"));*/ error = set_parent_dir(sbp, entryblock, ip->i_di.di_num.no_addr); if(error > 0) { log_err( _("%s: Hard link to block %" PRIu64" (0x%" PRIx64 - ") detected.\n"), filename, entryblock, entryblock); + ") detected.\n"), tmp_name, entryblock, entryblock); if(query( _("Clear hard link to directory? (y/n) "))) { bmodified(bh); @@ -510,12 +518,11 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, ds->entry_count++; return 0; } - } - else if (error < 0) { + } else if (error < 0) { stack; return -1; } - increment_link(sbp, de->de_inum.no_addr); + increment_link(sbp, entryblock); (*count)++; ds->entry_count++; /* End of checks */ @@ -650,7 +657,7 @@ static inline int is_system_dir(struct gfs2_sbd *sbp, uint64_t block) */ int pass2(struct gfs2_sbd *sbp) { - uint64_t i; + uint64_t dirblk; uint8_t q; struct dir_status ds = {0}; struct gfs2_inode *ip; @@ -679,43 +686,44 @@ int pass2(struct gfs2_sbd *sbp) } log_info( _("Checking directory inodes.\n")); /* Grab each directory inode, and run checks on it */ - for(i = 0; i < last_fs_block; i++) { - warm_fuzzy_stuff(i); + for(dirblk = 0; dirblk < last_fs_block; dirblk++) { + warm_fuzzy_stuff(dirblk); if (skip_this_pass || fsck_abort) /* if asked to skip the rest */ return FSCK_OK; /* Skip the system inodes - they're checked above */ - if (is_system_dir(sbp, i)) + if (is_system_dir(sbp, dirblk)) continue; - q = block_type(i); + q = block_type(dirblk); if(q != gfs2_inode_dir) continue; log_debug( _("Checking directory inode at block %"PRIu64" (0x%" - PRIx64 ")\n"), i, i); + PRIx64 ")\n"), dirblk, dirblk); memset(&ds, 0, sizeof(ds)); pass2_fxns.private = (void *) &ds; if(ds.q == gfs2_bad_block) { /* First check that the directory's metatree * is valid */ - ip = fsck_load_inode(sbp, i); + ip = fsck_load_inode(sbp, dirblk); if(check_metatree(ip, &pass2_fxns)) { fsck_inode_put(&ip); stack; return FSCK_ERROR; } } - error = check_dir(sbp, i, &pass2_fxns); + error = check_dir(sbp, dirblk, &pass2_fxns); if(error < 0) { stack; return FSCK_ERROR; } if (error > 0) { struct dir_info *di = NULL; - error = find_di(sbp, i, &di); + + error = find_di(sbp, dirblk, &di); if(error < 0) { stack; return FSCK_ERROR; @@ -724,30 +732,33 @@ int pass2(struct gfs2_sbd *sbp) /* FIXME: factor */ if(query( _("Remove directory entry for bad" " inode %"PRIu64" (0x%" PRIx64 ") in %"PRIu64 - " (0x%" PRIx64 ")? (y/n)"), i, i, di->treewalk_parent, + " (0x%" PRIx64 ")? (y/n)"), + dirblk, dirblk, di->treewalk_parent, di->treewalk_parent)) { - error = remove_dentry_from_dir(sbp, di->treewalk_parent, - i); + error = remove_dentry_from_dir(sbp, + di->treewalk_parent, + dirblk); if(error < 0) { stack; return FSCK_ERROR; } if(error > 0) { log_warn( _("Unable to find dentry for %" - PRIu64 " (0x%" PRIx64 ") in %" PRIu64 - " (0x%" PRIx64 ")\n"), i, i, - di->treewalk_parent, di->treewalk_parent); + PRIu64 " (0x%" PRIx64 ") in %" PRIu64 + " (0x%" PRIx64 ")\n"), dirblk, dirblk, + di->treewalk_parent, di->treewalk_parent); } log_warn( _("Directory entry removed\n")); } else log_err( _("Directory entry to invalid inode remains.\n")); } - gfs2_blockmap_set(sbp, bl, i, gfs2_meta_inval); + gfs2_blockmap_set(sbp, bl, dirblk, gfs2_meta_inval); } - ip = fsck_load_inode(sbp, i); + ip = fsck_load_inode(sbp, dirblk); if(!ds.dotdir) { log_err(_("No '.' entry found for directory inode at " - "block %"PRIu64" (0x%" PRIx64 ")\n"), i, i); + "block %"PRIu64" (0x%" PRIx64 ")\n"), + dirblk, dirblk); if (query( _("Is it okay to add '.' entry? (y/n) "))) { sprintf(tmp_name, "."); diff --git a/gfs2/fsck/pass3.c b/gfs2/fsck/pass3.c index bcca68c..c1986f3 100644 --- a/gfs2/fsck/pass3.c +++ b/gfs2/fsck/pass3.c @@ -55,11 +55,12 @@ static int attach_dotdot_to(struct gfs2_sbd *sbp, uint64_t newdotdot, bmodified(ip->i_bh); fsck_inode_put(&ip); fsck_inode_put(&pip); + free(filename); return 0; } static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sbp, - struct dir_info *di) + struct dir_info *di) { struct dir_info *pdi; uint8_t q_dotdot, q_treewalk; @@ -98,8 +99,7 @@ static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sbp, di->dotdot_parent, di->dinode); di->dotdot_parent = di->treewalk_parent; } - } - else { + } else { if(q_treewalk != gfs2_inode_dir) { int error = 0; log_warn( _(".. parent is valid, but treewalk" @@ -133,10 +133,11 @@ static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sbp, } else { log_err( _("Both .. and treewalk parents are " - "directories, going with treewalk for " - "now...\n")); + "directories, going with treewalk " + "for now...\n")); attach_dotdot_to(sbp, di->treewalk_parent, - di->dotdot_parent, di->dinode); + di->dotdot_parent, + di->dinode); di->dotdot_parent = di->treewalk_parent; } } diff --git a/gfs2/fsck/pass4.c b/gfs2/fsck/pass4.c index b3f28d7..a28dec6 100644 --- a/gfs2/fsck/pass4.c +++ b/gfs2/fsck/pass4.c @@ -24,7 +24,8 @@ struct metawalk_fxns pass4_fxns_delete = { static int fix_inode_count(struct gfs2_sbd *sbp, struct inode_info *ii, struct gfs2_inode *ip) { - log_info( _("Fixing inode count for %llu (0x%llx) \n"), + log_info( _("Fixing inode link count (%d->%d) for %llu (0x%llx) \n"), + ip->i_di.di_nlink, ii->counted_links, (unsigned long long)ip->i_di.di_num.no_addr, (unsigned long long)ip->i_di.di_num.no_addr); if(ip->i_di.di_nlink == ii->counted_links) @@ -55,8 +56,6 @@ static int scan_inode_list(struct gfs2_sbd *sbp, osi_list_t *list) { log_crit( _("osi_list_foreach broken in scan_info_list!!\n")); exit(FSCK_ERROR); } - log_debug( _("Checking reference count on inode at block %" PRIu64 - " (0x%" PRIx64 ")\n"), ii->inode, ii->inode); if(ii->counted_links == 0) { log_err( _("Found unlinked inode at %" PRIu64 " (0x%" PRIx64 ")\n"), ii->inode, ii->inode); @@ -87,8 +86,11 @@ static int scan_inode_list(struct gfs2_sbd *sbp, osi_list_t *list) { q != gfs2_inode_chr && q != gfs2_inode_fifo && q != gfs2_inode_sock) { - log_err( _("Unlinked block marked as inode is " - "not an inode (%d)\n"), q); + log_err( _("Unlinked block %lld (0x%llx) " + "marked as inode is " + "not an inode (%d)\n"), + (unsigned long long)ii->inode, + (unsigned long long)ii->inode, q); ip = fsck_load_inode(sbp, ii->inode); if(query(_("Delete unlinked inode? (y/n) "))) { check_inode_eattr(ip, @@ -126,8 +128,7 @@ static int scan_inode_list(struct gfs2_sbd *sbp, osi_list_t *list) { stack; fsck_inode_put(&ip); return -1; - } - else { + } else { fix_inode_count(sbp, ii, ip); lf_addition = 1; } @@ -148,8 +149,10 @@ static int scan_inode_list(struct gfs2_sbd *sbp, osi_list_t *list) { fix_inode_count(sbp, ii, ip); bmodified(ip->i_bh); fsck_inode_put(&ip); /* out, brelse, free */ - log_warn( _("Link count updated for inode %" - PRIu64 " (0x%" PRIx64 ") \n"), ii->inode, ii->inode); + log_warn( _("Link count updated to %d for " + "inode %" PRIu64 " (0x%" + PRIx64 ") \n"), ii->link_count, + ii->inode, ii->inode); } else { log_err( _("Link count for inode %" PRIu64 " (0x%" PRIx64 ") still incorrect\n"), ii->inode, ii->inode); diff --git a/gfs2/fsck/pass5.c b/gfs2/fsck/pass5.c index 3448204..41da203 100644 --- a/gfs2/fsck/pass5.c +++ b/gfs2/fsck/pass5.c @@ -43,7 +43,7 @@ static int convert_mark(uint8_t q, uint32_t *count) return GFS2_BLKST_USED; default: - log_err( _("Invalid state %d found\n"), q); + log_err( _("Invalid block type %d found\n"), q); return -1; } return -1; @@ -122,9 +122,9 @@ static int check_block_status(struct gfs2_sbd *sbp, char *buffer, unsigned int b log_err( _("Metadata type is %u (%s)\n"), q, block_type_string(q)); - if(query( _("Fix bitmap for block %" PRIu64 - " (0x%" PRIx64 ") ? (y/n) "), - block, block)) { + if(query(_("Fix bitmap for block %" PRIu64 + " (0x%" PRIx64 ") ? (y/n) "), + block, block)) { if(gfs2_set_bitmap(sbp, block, block_status)) log_err( _("Failed.\n")); else diff --git a/gfs2/fsck/rgrepair.c b/gfs2/fsck/rgrepair.c index 0cb99d2..2dace5d 100644 --- a/gfs2/fsck/rgrepair.c +++ b/gfs2/fsck/rgrepair.c @@ -19,11 +19,11 @@ struct special_blocks false_rgrps; #define ri_compare(rg, ondisk, expected, field, fmt) \ if (ondisk.field != expected.field) { \ - log_warn("rindex #%d " #field " discrepancy: index 0x%" fmt \ - " != expected: 0x%" fmt "\n", \ - rg + 1, ondisk.field, expected.field); \ - ondisk.field = expected.field; \ - rindex_modified = TRUE; \ + log_warn( _("rindex #%d " #field " discrepancy: index 0x%" \ + fmt " != expected: 0x%" fmt "\n"), \ + rg + 1, ondisk.field, expected.field); \ + ondisk.field = expected.field; \ + rindex_modified = TRUE; \ } /* diff --git a/gfs2/fsck/util.c b/gfs2/fsck/util.c index 2d601ef..a705975 100644 --- a/gfs2/fsck/util.c +++ b/gfs2/fsck/util.c @@ -58,7 +58,7 @@ void warm_fuzzy_stuff(uint64_t block) static uint64_t one_percent = 0; static struct timeval tv; static uint32_t seconds = 0; - + if (!one_percent) one_percent = last_fs_block / 100; if (block - last_reported_block >= one_percent) { @@ -160,7 +160,7 @@ void gfs2_dup_set(uint64_t block) b = malloc(sizeof(struct dup_blks)); if (b) { memset(b, 0, sizeof(*b)); - b->block_no = block; + b->block = block; osi_list_init(&b->ref_inode_list); osi_list_add(&b->list, &dup_blocks.list); } diff --git a/gfs2/libgfs2/block_list.c b/gfs2/libgfs2/block_list.c index aa774be..bc8babc 100644 --- a/gfs2/libgfs2/block_list.c +++ b/gfs2/libgfs2/block_list.c @@ -91,7 +91,6 @@ void gfs2_special_set(struct special_blocks *blocklist, uint64_t block) b->block = block; osi_list_add(&b->list, &blocklist->list); } - return; } void gfs2_special_clear(struct special_blocks *blocklist, uint64_t block) diff --git a/gfs2/libgfs2/buf.c b/gfs2/libgfs2/buf.c index 5b8d29d..5a0f718 100644 --- a/gfs2/libgfs2/buf.c +++ b/gfs2/libgfs2/buf.c @@ -69,7 +69,7 @@ int bwrite(struct gfs2_buffer_head *bh) if (write(sdp->device_fd, bh->b_data, sdp->bsize) != sdp->bsize) return -1; sdp->writes++; - bh->b_changed = 0; + bh->b_modified = 0; return 0; } @@ -79,7 +79,7 @@ int brelse(struct gfs2_buffer_head *bh) if (bh->b_blocknr == -1) printf("Double free!\n"); - if (bh->b_changed) + if (bh->b_modified) error = bwrite(bh); bh->b_blocknr = -1; if (bh->b_altlist.next && !osi_list_empty(&bh->b_altlist)) diff --git a/gfs2/libgfs2/fs_ops.c b/gfs2/libgfs2/fs_ops.c index b3b527f..bc8319e 100644 --- a/gfs2/libgfs2/fs_ops.c +++ b/gfs2/libgfs2/fs_ops.c @@ -93,7 +93,7 @@ void inode_put(struct gfs2_inode **ip_in) uint64_t block = ip->i_di.di_num.no_addr; struct gfs2_sbd *sdp = ip->i_sbd; - if (ip->i_bh->b_changed) { + if (ip->i_bh->b_modified) { gfs2_dinode_out(&ip->i_di, ip->i_bh); if (!ip->bh_owned && is_system_inode(sdp, block)) fprintf(stderr, "Warning: Change made to inode " @@ -154,8 +154,9 @@ static uint64_t blk_alloc_i(struct gfs2_sbd *sdp, unsigned int type) found: if (bn >= ri->ri_bitbytes * GFS2_NBBY) - die("allocation is broken (2): %u %u %"PRIu64" %u\n", - bn, ri->ri_bitbytes * GFS2_NBBY, + die("allocation is broken (2): bn: %u %u rgrp: %"PRIu64 + " (0x%" PRIx64 ") Free:%u\n", + bn, ri->ri_bitbytes * GFS2_NBBY, (uint64_t)rl->ri.ri_addr, (uint64_t)rl->ri.ri_addr, rl->rg.rg_free); switch (type) { @@ -234,15 +235,14 @@ void unstuff_dinode(struct gfs2_inode *ip) if (ip->i_di.di_size) { if (isdir) { + struct gfs2_meta_header mh; + block = meta_alloc(ip); bh = bget(sdp, block); - { - struct gfs2_meta_header mh; - mh.mh_magic = GFS2_MAGIC; - mh.mh_type = GFS2_METATYPE_JD; - mh.mh_format = GFS2_FORMAT_JD; - gfs2_meta_header_out(&mh, bh); - } + mh.mh_magic = GFS2_MAGIC; + mh.mh_type = GFS2_METATYPE_JD; + mh.mh_format = GFS2_FORMAT_JD; + gfs2_meta_header_out(&mh, bh); buffer_copy_tail(sdp, bh, sizeof(struct gfs2_meta_header), @@ -312,15 +312,14 @@ void build_height(struct gfs2_inode *ip, int height) } if (new_block) { + struct gfs2_meta_header mh; + block = meta_alloc(ip); bh = bget(sdp, block); - { - struct gfs2_meta_header mh; - mh.mh_magic = GFS2_MAGIC; - mh.mh_type = GFS2_METATYPE_IN; - mh.mh_format = GFS2_FORMAT_IN; - gfs2_meta_header_out(&mh, bh); - } + mh.mh_magic = GFS2_MAGIC; + mh.mh_type = GFS2_METATYPE_IN; + mh.mh_format = GFS2_FORMAT_IN; + gfs2_meta_header_out(&mh, bh); buffer_copy_tail(sdp, bh, sizeof(struct gfs2_meta_header), ip->i_bh, sizeof(struct gfs2_dinode)); @@ -567,7 +566,7 @@ int gfs2_readi(struct gfs2_inode *ip, void *buf, } static void copy_from_mem(struct gfs2_buffer_head *bh, void **buf, - unsigned int offset, unsigned int size) + unsigned int offset, unsigned int size) { char **p = (char **)buf; @@ -763,7 +762,7 @@ static int dirent_alloc(struct gfs2_inode *dip, struct gfs2_buffer_head *bh, memset(new, 0, sizeof(struct gfs2_dirent)); new->de_rec_len = cpu_to_be16(cur_rec_len - - GFS2_DIRENT_SIZE(cur_name_len)); + GFS2_DIRENT_SIZE(cur_name_len)); new->de_name_len = cpu_to_be16(name_len); new_rec_len = be16_to_cpu(new->de_rec_len); @@ -812,14 +811,13 @@ void dirent2_del(struct gfs2_inode *dip, struct gfs2_buffer_head *bh, } void gfs2_get_leaf_nr(struct gfs2_inode *dip, uint32_t lindex, - uint64_t *leaf_out) + uint64_t *leaf_out) { uint64_t leaf_no; int count; - count = gfs2_readi(dip, (char *)&leaf_no, - lindex * sizeof(uint64_t), - sizeof(uint64_t)); + count = gfs2_readi(dip, (char *)&leaf_no, lindex * sizeof(uint64_t), + sizeof(uint64_t)); if (count != sizeof(uint64_t)) die("gfs2_get_leaf_nr: Bad internal read.\n"); @@ -838,7 +836,8 @@ void gfs2_put_leaf_nr(struct gfs2_inode *dip, uint32_t inx, uint64_t leaf_out) die("gfs2_put_leaf_nr: Bad internal write.\n"); } -static void dir_split_leaf(struct gfs2_inode *dip, uint32_t lindex, uint64_t leaf_no) +static void dir_split_leaf(struct gfs2_inode *dip, uint32_t lindex, + uint64_t leaf_no) { struct gfs2_buffer_head *nbh, *obh; struct gfs2_leaf *nleaf, *oleaf; @@ -875,16 +874,11 @@ static void dir_split_leaf(struct gfs2_inode *dip, uint32_t lindex, uint64_t lea fprintf(stderr, "Out of memory in %s\n", __FUNCTION__); exit(-1); } - count = gfs2_readi(dip, (char *)lp, start * sizeof(uint64_t), - half_len * sizeof(uint64_t)); - if (count != half_len * sizeof(uint64_t)) - die("dir_split_leaf (1)\n"); - for (x = 0; x < half_len; x++) lp[x] = cpu_to_be64(bn); count = gfs2_writei(dip, (char *)lp, start * sizeof(uint64_t), - half_len * sizeof(uint64_t)); + half_len * sizeof(uint64_t)); if (count != half_len * sizeof(uint64_t)) die("dir_split_leaf (2)\n"); @@ -976,7 +970,7 @@ static void dir_double_exhash(struct gfs2_inode *dip) } count = gfs2_writei(dip, (char *)buf + sdp->sd_hash_bsize, - block * sdp->bsize, sdp->bsize); + block * sdp->bsize, sdp->bsize); if (count != sdp->bsize) die("dir_double_exhash (2)\n"); @@ -1062,8 +1056,8 @@ static void dir_e_add(struct gfs2_inode *dip, const char *filename, int len, uint32_t hash; uint64_t leaf_no, bn; - restart: hash = gfs2_disk_hash(filename, len); +restart: /* Have to kludge because (hash >> 32) gives hash for some reason. */ if (dip->i_di.di_depth) lindex = hash >> (32 - dip->i_di.di_depth); @@ -1094,15 +1088,14 @@ static void dir_e_add(struct gfs2_inode *dip, const char *filename, int len, continue; } else { + struct gfs2_meta_header mh; + bn = meta_alloc(dip); nbh = bget(dip->i_sbd, bn); - { - struct gfs2_meta_header mh; - mh.mh_magic = GFS2_MAGIC; - mh.mh_type = GFS2_METATYPE_LF; - mh.mh_format = GFS2_FORMAT_LF; - gfs2_meta_header_out(&mh, nbh); - } + mh.mh_magic = GFS2_MAGIC; + mh.mh_type = GFS2_METATYPE_LF; + mh.mh_format = GFS2_FORMAT_LF; + gfs2_meta_header_out(&mh, nbh); leaf->lf_next = cpu_to_be64(bn); diff --git a/gfs2/libgfs2/gfs2_log.c b/gfs2/libgfs2/gfs2_log.c index 907c5f7..622589b 100644 --- a/gfs2/libgfs2/gfs2_log.c +++ b/gfs2/libgfs2/gfs2_log.c @@ -50,19 +50,16 @@ void print_msg(int priority, const char *file, int line, vfprintf(stderr, format, args); break; } - return; } void print_fsck_log(int iif, int priority, const char *file, int line, const char *format, ...) { - va_list args; const char *transform; - va_start(args, format); - + va_start(args, format); transform = _(format); if((_state.print_level == priority) || @@ -150,7 +147,6 @@ char generic_interrupt(const char *caller, const char *where, int gfs2_query(int *setonabort, struct gfs2_options *opts, const char *format, ...) { - va_list args; const char *transform; char response; diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h index 3b843e5..b0745aa 100644 --- a/gfs2/libgfs2/libgfs2.h +++ b/gfs2/libgfs2/libgfs2.h @@ -111,7 +111,7 @@ struct rgrp_list { struct gfs2_buffer_head { osi_list_t b_altlist; /* alternate list */ uint64_t b_blocknr; - int b_changed; + int b_modified; char *b_data; struct gfs2_sbd *sdp; }; @@ -329,7 +329,7 @@ extern struct gfs2_buffer_head *__bread(struct gfs2_sbd *sdp, uint64_t num, extern int bwrite(struct gfs2_buffer_head *bh); extern int brelse(struct gfs2_buffer_head *bh); -#define bmodified(bh) do { bh->b_changed = 1; } while(0) +#define bmodified(bh) do { bh->b_modified = 1; } while(0) #define bget_generic(bl, num, find, read) __bget_generic(bl, num, find, read, \ __LINE__, \ @@ -700,7 +700,6 @@ extern void gfs2_leaf_print(struct gfs2_leaf *lf); extern void gfs2_ea_header_print(struct gfs2_ea_header *ea, char *name); extern void gfs2_log_header_print(struct gfs2_log_header *lh); extern void gfs2_log_descriptor_print(struct gfs2_log_descriptor *ld); -extern void gfs2_inum_range_print(struct gfs2_inum_range *ir); extern void gfs2_statfs_change_print(struct gfs2_statfs_change *sc); extern void gfs2_quota_change_print(struct gfs2_quota_change *qc); diff --git a/gfs2/libgfs2/super.c b/gfs2/libgfs2/super.c index 0d65928..ca7bf09 100644 --- a/gfs2/libgfs2/super.c +++ b/gfs2/libgfs2/super.c @@ -131,7 +131,7 @@ int ji_update(struct gfs2_sbd *sdp) int i; if(!ip) { - log_crit("Journal inode not found.\n"); + log_crit("Journal index inode not found.\n"); return -1; }
1
0
0
0
cluster: STABLE3 - libgfs2, fsck.gfs2: simplify block_query code
by Bob Peterson
26 Jan '10
26 Jan '10
Gitweb:
http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=48…
Commit: 48cd85089a1a12d4c36fca20b9b3fed362b8f4b7 Parent: 2f222faced71bb3a90d1ed9d1dd4af3bede7eaf6 Author: Bob Peterson <bob(a)ganesha.peterson> AuthorDate: Wed Jan 20 12:31:38 2010 -0600 Committer: Bob Peterson <rpeterso(a)redhat.com> CommitterDate: Tue Jan 26 14:39:28 2010 -0600 libgfs2, fsck.gfs2: simplify block_query code This patch simplifies the block query code. Now that the blockmap code doesn't have the duplicate block reference responsibilities, we don't need the query info to be in its own structure. The block query can be reduced to a simple fetch from memory and mask off the bits we need. The block query used to check for a valid block range. Now, for performance reasons, that's the responsibility of the caller. Most of the callers check for a valid range anyway, so checking it in the query was a waste of time. This is for better performance and makes the code simpler and more readable. rhbz#455300 --- gfs2/fsck/fsck.h | 2 +- gfs2/fsck/lost_n_found.c | 10 ++--- gfs2/fsck/main.c | 16 +++----- gfs2/fsck/metawalk.c | 13 ++----- gfs2/fsck/pass1.c | 81 +++++++++++---------------------------------- gfs2/fsck/pass1b.c | 24 +++++-------- gfs2/fsck/pass1c.c | 28 +++++---------- gfs2/fsck/pass2.c | 51 ++++++++++++---------------- gfs2/fsck/pass3.c | 56 ++++++++++-------------------- gfs2/fsck/pass4.c | 27 +++++++-------- gfs2/fsck/pass5.c | 16 ++++---- gfs2/fsck/util.c | 6 ++-- gfs2/fsck/util.h | 15 ++++++++- gfs2/libgfs2/block_list.c | 15 -------- gfs2/libgfs2/libgfs2.h | 6 --- 15 files changed, 131 insertions(+), 235 deletions(-) diff --git a/gfs2/fsck/fsck.h b/gfs2/fsck/fsck.h index 05a1147..a15bc33 100644 --- a/gfs2/fsck/fsck.h +++ b/gfs2/fsck/fsck.h @@ -44,7 +44,7 @@ struct dir_info struct dir_status { uint8_t dotdir:1; uint8_t dotdotdir:1; - struct gfs2_block_query q; + uint8_t q; uint32_t entry_count; }; diff --git a/gfs2/fsck/lost_n_found.c b/gfs2/fsck/lost_n_found.c index ffa88b2..bc07d7b 100644 --- a/gfs2/fsck/lost_n_found.c +++ b/gfs2/fsck/lost_n_found.c @@ -12,6 +12,7 @@ #include "libgfs2.h" #include "lost_n_found.h" #include "link.h" +#include "util.h" /* add_inode_to_lf - Add dir entry to lost+found for the inode * @ip: inode to add to lost + found @@ -29,16 +30,13 @@ int add_inode_to_lf(struct gfs2_inode *ip){ __be32 inode_type; if(!lf_dip) { - struct gfs2_block_query q = {0}; + uint8_t q; log_info( _("Locating/Creating lost and found directory\n")); lf_dip = createi(ip->i_sbd->md.rooti, "lost+found", S_IFDIR | 0700, 0); - if(gfs2_block_check(ip->i_sbd, bl, lf_dip->i_di.di_num.no_addr, &q)) { - stack; - return -1; - } - if(q.block_type != gfs2_inode_dir) { + q = block_type(lf_dip->i_di.di_num.no_addr); + if(q != gfs2_inode_dir) { /* This is a new lost+found directory, so set its * block type and increment link counts for * the directories */ diff --git a/gfs2/fsck/main.c b/gfs2/fsck/main.c index 34cc045..c2f9722 100644 --- a/gfs2/fsck/main.c +++ b/gfs2/fsck/main.c @@ -15,6 +15,7 @@ #include "libgfs2.h" #include "fsck.h" #include "osi_list.h" +#include "util.h" struct gfs2_options opts = {0}; struct gfs2_inode *lf_dip; /* Lost and found directory inode */ @@ -161,22 +162,17 @@ static int check_system_inode(struct gfs2_inode *sysinode, const char *filename, /* FIXME: check this block's validity */ - if(gfs2_block_check(sysinode->i_sbd, bl, iblock, &ds.q)) { - log_crit( _("Can't get %s inode block %" PRIu64 " (0x%" - PRIx64 ") from block list\n"), filename, - iblock, iblock); - return -1; - } + ds.q = block_type(iblock); /* If the inode exists but the block is marked */ /* free, we might be recovering from a corrupt */ /* bitmap. In that case, don't rebuild the inode. */ /* Just reuse the inode and fix the bitmap. */ - if (ds.q.block_type == gfs2_block_free) { + if (ds.q == gfs2_block_free) { log_info( _("The inode exists but the block is not marked 'in use'; fixing it.\n")); gfs2_blockmap_set(sysinode->i_sbd, bl, sysinode->i_di.di_num.no_addr, mark); - ds.q.block_type = mark; + ds.q = mark; if (mark == gfs2_inode_dir) add_to_dir_list(sysinode->i_sbd, sysinode->i_di.di_num.no_addr); @@ -188,14 +184,14 @@ static int check_system_inode(struct gfs2_inode *sysinode, const char *filename, * create a new inode and get it all setup - of course, * everything will be in lost+found then, but we *need* our * system inodes before we can do any of that. */ - if(!sysinode || ds.q.block_type != mark) { + if(!sysinode || ds.q != mark) { log_err( _("Invalid or missing %s system inode.\n"), filename); if (query(_("Create new %s system inode? (y/n) "), filename)) { builder(sysinode->i_sbd); gfs2_blockmap_set(sysinode->i_sbd, bl, sysinode->i_di.di_num.no_addr, mark); - ds.q.block_type = mark; + ds.q = mark; if (mark == gfs2_inode_dir) add_to_dir_list(sysinode->i_sbd, sysinode->i_di.di_num.no_addr); diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c index aaa1144..d348123 100644 --- a/gfs2/fsck/metawalk.c +++ b/gfs2/fsck/metawalk.c @@ -1086,7 +1086,7 @@ int remove_dentry_from_dir(struct gfs2_sbd *sbp, uint64_t dir, uint64_t dentryblock) { struct metawalk_fxns remove_dentry_fxns = {0}; - struct gfs2_block_query q; + uint8_t q; int error; log_debug( _("Removing dentry %" PRIu64 " (0x%" PRIx64 ") from directory %" @@ -1098,11 +1098,8 @@ int remove_dentry_from_dir(struct gfs2_sbd *sbp, uint64_t dir, remove_dentry_fxns.private = &dentryblock; remove_dentry_fxns.check_dentry = remove_dentry; - if(gfs2_block_check(sbp, bl, dir, &q)) { - stack; - return -1; - } - if(q.block_type != gfs2_inode_dir) { + q = block_type(dir); + if(q != gfs2_inode_dir) { log_info( _("Parent block is not a directory...ignoring\n")); return 1; } @@ -1193,11 +1190,7 @@ int delete_blocks(struct gfs2_inode *ip, uint64_t block, struct gfs2_buffer_head **bh, const char *btype, void *private) { - struct gfs2_block_query q = {0}; - if (gfs2_check_range(ip->i_sbd, block) == 0) { - if (gfs2_block_check(ip->i_sbd, bl, block, &q)) - return 0; if(!is_duplicate(block)) { log_info( _("Deleting %s block %lld (0x%llx) as part " "of inode %lld (0x%llx)\n"), btype, diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c index 5baf351..2d1aed5 100644 --- a/gfs2/fsck/pass1.c +++ b/gfs2/fsck/pass1.c @@ -83,7 +83,7 @@ static int leaf(struct gfs2_inode *ip, uint64_t block, static int check_metalist(struct gfs2_inode *ip, uint64_t block, struct gfs2_buffer_head **bh, void *private) { - struct gfs2_block_query q = {0}; + uint8_t q; int found_dup = 0; struct gfs2_buffer_head *nbh; struct block_count *bc = (struct block_count *)private; @@ -97,13 +97,10 @@ static int check_metalist(struct gfs2_inode *ip, uint64_t block, return 1; } - if(gfs2_block_check(ip->i_sbd, bl, block, &q)) { - stack; - return -1; - } - if(q.block_type != gfs2_block_free) { + q = block_type(block); + if(q != gfs2_block_free) { log_err( _("Found duplicate block referenced as metadata in " - "indirect block - was marked %d\n"), q.block_type); + "indirect block - was marked %d\n"), q); gfs2_dup_set(block); found_dup = 1; } @@ -133,7 +130,7 @@ static int check_metalist(struct gfs2_inode *ip, uint64_t block, static int check_data(struct gfs2_inode *ip, uint64_t block, void *private) { - struct gfs2_block_query q = {0}; + uint8_t q; struct block_count *bc = (struct block_count *) private; int error = 0, btype; @@ -150,20 +147,15 @@ static int check_data(struct gfs2_inode *ip, uint64_t block, void *private) gfs2_bad_block); return 1; } - if(gfs2_block_check(ip->i_sbd, bl, block, &q)) { - stack; - log_err( _("Found bad block referenced as data at %" - PRIu64 " (0x%"PRIx64 ")\n"), block, block); - return -1; - } - if(q.block_type != gfs2_block_free) { + q = block_type(block); + if(q != gfs2_block_free) { log_err( _("Found duplicate block referenced as data at %" PRIu64 " (0x%"PRIx64 ")\n"), block, block); - if (q.block_type != gfs2_meta_inval) { + if (q != gfs2_meta_inval) { gfs2_dup_set(block); /* If the prev ref was as data, this is likely a data block, so keep the block count for both refs. */ - if (q.block_type == gfs2_block_used) + if (q == gfs2_block_used) bc->data_count++; return 1; } @@ -244,11 +236,6 @@ static int ask_remove_inode_eattr(struct gfs2_inode *ip, (unsigned long long)ip->i_di.di_num.no_addr); if (query( _("Clear all Extended Attributes from the " "inode? (y/n) "))) { - struct gfs2_block_query q; - if(gfs2_block_check(ip->i_sbd, bl, ip->i_di.di_eattr, &q)) { - stack; - return -1; - } if (!remove_inode_eattr(ip, bc, is_duplicate(ip->i_di.di_eattr))) log_err( _("Extended attributes were removed.\n")); @@ -305,7 +292,7 @@ static int check_eattr_indir(struct gfs2_inode *ip, uint64_t indirect, { struct gfs2_sbd *sdp = ip->i_sbd; int ret = 0; - struct gfs2_block_query q = {0}; + uint8_t q; struct block_count *bc = (struct block_count *) private; /* This inode contains an eattr - it may be invalid, but the @@ -318,10 +305,7 @@ static int check_eattr_indir(struct gfs2_inode *ip, uint64_t indirect, * in pass1c */ return 1; } - if(gfs2_block_check(sdp, bl, indirect, &q)) { - stack; - return -1; - } + q = block_type(indirect); /* Special duplicate processing: If we have an EA block, check if it really is an EA. If it is, let duplicate @@ -329,7 +313,7 @@ static int check_eattr_indir(struct gfs2_inode *ip, uint64_t indirect, count it as a duplicate. */ *bh = bread(sdp, indirect); if(gfs2_check_meta(*bh, GFS2_METATYPE_IN)) { - if(q.block_type != gfs2_block_free) { /* Duplicate? */ + if(q != gfs2_block_free) { /* Duplicate? */ if (!clear_eas(ip, bc, indirect, 1, _("Bad indirect Extended Attribute " "duplicate found"))) { @@ -343,7 +327,7 @@ static int check_eattr_indir(struct gfs2_inode *ip, uint64_t indirect, "type")); return 1; } - if(q.block_type != gfs2_block_free) { /* Duplicate? */ + if(q != gfs2_block_free) { /* Duplicate? */ log_err( _("Inode #%llu (0x%llx): Duplicate Extended " "Attribute indirect block found at #%llu " "(0x%llx).\n"), @@ -400,19 +384,16 @@ static int check_leaf_block(struct gfs2_inode *ip, uint64_t block, int btype, { struct gfs2_buffer_head *leaf_bh = NULL; struct gfs2_sbd *sdp = ip->i_sbd; - struct gfs2_block_query q = {0}; + uint8_t q; struct block_count *bc = (struct block_count *) private; - if(gfs2_block_check(sdp, bl, block, &q)) { - stack; - return -1; - } + q = block_type(block); /* Special duplicate processing: If we have an EA block, check if it really is an EA. If it is, let duplicate handling sort it out. If it isn't, clear it but don't count it as a duplicate. */ leaf_bh = bread(sdp, block); if(gfs2_check_meta(leaf_bh, btype)) { - if(q.block_type != gfs2_block_free) { /* Duplicate? */ + if(q != gfs2_block_free) { /* Duplicate? */ clear_eas(ip, bc, block, 1, _("Bad Extended Attribute duplicate found")); } else { @@ -423,7 +404,7 @@ static int check_leaf_block(struct gfs2_inode *ip, uint64_t block, int btype, brelse(leaf_bh); return 1; } - if(q.block_type != gfs2_block_free) { /* Duplicate? */ + if(q != gfs2_block_free) { /* Duplicate? */ log_debug( _("Duplicate block found at #%lld (0x%llx).\n"), (unsigned long long)block, (unsigned long long)block); @@ -567,14 +548,8 @@ static int check_eattr_entries(struct gfs2_inode *ip, static int clear_metalist(struct gfs2_inode *ip, uint64_t block, struct gfs2_buffer_head **bh, void *private) { - struct gfs2_block_query q = {0}; - *bh = NULL; - if(gfs2_block_check(ip->i_sbd, bl, block, &q)) { - stack; - return -1; - } if(!is_duplicate(block)) { gfs2_blockmap_set(ip->i_sbd, bl, block, gfs2_block_free); return 0; @@ -584,12 +559,6 @@ static int clear_metalist(struct gfs2_inode *ip, uint64_t block, static int clear_data(struct gfs2_inode *ip, uint64_t block, void *private) { - struct gfs2_block_query q = {0}; - - if(gfs2_block_check(ip->i_sbd, bl, block, &q)) { - stack; - return -1; - } if(!is_duplicate(block)) { gfs2_blockmap_set(ip->i_sbd, bl, block, gfs2_block_free); return 0; @@ -601,15 +570,9 @@ static int clear_data(struct gfs2_inode *ip, uint64_t block, void *private) static int clear_leaf(struct gfs2_inode *ip, uint64_t block, struct gfs2_buffer_head *bh, void *private) { - struct gfs2_block_query q = {0}; - log_crit( _("Clearing leaf #%" PRIu64 " (0x%" PRIx64 ")\n"), block, block); - if(gfs2_block_check(ip->i_sbd, bl, block, &q)) { - stack; - return -1; - } if(!is_duplicate(block)) { log_crit( _("Setting leaf #%" PRIu64 " (0x%" PRIx64 ") invalid\n"), block, block); @@ -655,7 +618,7 @@ int add_to_dir_list(struct gfs2_sbd *sbp, uint64_t block) static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh, uint64_t block) { - struct gfs2_block_query q = {0}; + uint8_t q; struct gfs2_inode *ip; int error; struct block_count bc = {0}; @@ -683,12 +646,8 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh, " (0x%" PRIx64 ") not fixed\n"), block, block); } - if(gfs2_block_check(sdp, bl, block, &q)) { - stack; - fsck_inode_put(&ip); - return -1; - } - if(q.block_type != gfs2_block_free) { + q = block_type(block); + if(q != gfs2_block_free) { log_err( _("Found duplicate block referenced as an inode at " "#%" PRIu64 " (0x%" PRIx64 ")\n"), block, block); gfs2_dup_set(block); diff --git a/gfs2/fsck/pass1b.c b/gfs2/fsck/pass1b.c index a25e4da..4827534 100644 --- a/gfs2/fsck/pass1b.c +++ b/gfs2/fsck/pass1b.c @@ -494,7 +494,7 @@ int pass1b(struct gfs2_sbd *sbp) { struct dup_blks *b; uint64_t i; - struct gfs2_block_query q; + uint8_t q; osi_list_t *tmp = NULL, *x; struct metawalk_fxns find_dirents = {0}; int rc = FSCK_OK; @@ -519,18 +519,14 @@ int pass1b(struct gfs2_sbd *sbp) goto out; log_debug( _("Scanning block %" PRIu64 " (0x%" PRIx64 ") for inodes\n"), i, i); - if(gfs2_block_check(sbp, bl, i, &q)) { - stack; - rc = FSCK_ERROR; - goto out; - } - if((q.block_type == gfs2_inode_dir) || - (q.block_type == gfs2_inode_file) || - (q.block_type == gfs2_inode_lnk) || - (q.block_type == gfs2_inode_blk) || - (q.block_type == gfs2_inode_chr) || - (q.block_type == gfs2_inode_fifo) || - (q.block_type == gfs2_inode_sock)) { + q = block_type(i); + if((q == gfs2_inode_dir) || + (q == gfs2_inode_file) || + (q == gfs2_inode_lnk) || + (q == gfs2_inode_blk) || + (q == gfs2_inode_chr) || + (q == gfs2_inode_fifo) || + (q == gfs2_inode_sock)) { osi_list_foreach_safe(tmp, &dup_blocks.list, x) { b = osi_list_entry(tmp, struct dup_blks, list); @@ -541,7 +537,7 @@ int pass1b(struct gfs2_sbd *sbp) } } } - if(q.block_type == gfs2_inode_dir) { + if(q == gfs2_inode_dir) { check_dir(sbp, i, &find_dirents); } } diff --git a/gfs2/fsck/pass1c.c b/gfs2/fsck/pass1c.c index e3bd010..4174363 100644 --- a/gfs2/fsck/pass1c.c +++ b/gfs2/fsck/pass1c.c @@ -72,7 +72,7 @@ static int check_eattr_indir(struct gfs2_inode *ip, uint64_t block, void *private) { struct gfs2_sbd *sbp = ip->i_sbd; - struct gfs2_block_query q; + uint8_t q; struct gfs2_buffer_head *indir_bh = NULL; if(gfs2_check_range(sbp, block)) { @@ -85,11 +85,8 @@ static int check_eattr_indir(struct gfs2_inode *ip, uint64_t block, (unsigned long long)ip->i_di.di_num.no_addr); return ask_remove_eattr(ip); } - else if (gfs2_block_check(sbp, bl, block, &q)) { - stack; - return -1; - } - else if(q.block_type != gfs2_indir_blk) { + q = block_type(block); + if(q != gfs2_indir_blk) { log_err( _("Extended attributes indirect block #%llu" " (0x%llx) for inode #%llu" " (0x%llx) invalid.\n"), @@ -111,7 +108,7 @@ static int check_eattr_leaf(struct gfs2_inode *ip, uint64_t block, void *private) { struct gfs2_sbd *sbp = ip->i_sbd; - struct gfs2_block_query q; + uint8_t q; if(gfs2_check_range(sbp, block)) { log_err( _("Extended attributes block for inode #%llu" @@ -120,11 +117,8 @@ static int check_eattr_leaf(struct gfs2_inode *ip, uint64_t block, (unsigned long long)ip->i_di.di_num.no_addr); return ask_remove_eattr(ip); } - else if (gfs2_block_check(sbp, bl, block, &q)) { - stack; - return -1; - } - else if(q.block_type != gfs2_meta_eattr) { + q = block_type(block); + if(q != gfs2_meta_eattr) { log_err( _("Extended attributes block for inode #%llu" " (0x%llx) invalid.\n"), (unsigned long long)ip->i_di.di_num.no_addr, @@ -209,14 +203,12 @@ static int check_eattr_extentry(struct gfs2_inode *ip, uint64_t *ea_ptr, struct gfs2_ea_header *ea_hdr, struct gfs2_ea_header *ea_hdr_prev, void *private) { - struct gfs2_block_query q; + uint8_t q; struct gfs2_sbd *sbp = ip->i_sbd; - if(gfs2_block_check(sbp, bl, be64_to_cpu(*ea_ptr), &q)) { - stack; - return -1; - } - if(q.block_type != gfs2_meta_eattr) { + + q = block_type(be64_to_cpu(*ea_ptr)); + if(q != gfs2_meta_eattr) { if(remove_eattr_entry(sbp, leaf_bh, ea_hdr, ea_hdr_prev)){ stack; return -1; diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c index 7453e47..5e60b50 100644 --- a/gfs2/fsck/pass2.c +++ b/gfs2/fsck/pass2.c @@ -101,9 +101,9 @@ static const char *de_type_string(uint8_t de_type) return de_types[3]; /* invalid */ } -static int check_file_type(uint8_t de_type, uint8_t block_type) +static int check_file_type(uint8_t de_type, uint8_t blk_type) { - switch(block_type) { + switch(blk_type) { case gfs2_inode_dir: if(de_type != DT_DIR) return 1; @@ -156,7 +156,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, uint16_t *count, void *priv) { struct gfs2_sbd *sbp = ip->i_sbd; - struct gfs2_block_query q = {0}; + uint8_t q; char tmp_name[MAX_FILENAME]; uint64_t entryblock; struct dir_status *ds = (struct dir_status *) priv; @@ -234,12 +234,9 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, return 0; } } - if(gfs2_block_check(sbp, bl, de->de_inum.no_addr, &q)) { - stack; - return -1; - } + q = block_type(de->de_inum.no_addr); /* Get the status of the directory inode */ - if(q.block_type == gfs2_bad_block) { + if(q == gfs2_bad_block) { /* This entry's inode has bad blocks in it */ /* Handle bad blocks */ @@ -266,10 +263,10 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, } } - if(q.block_type != gfs2_inode_dir && q.block_type != gfs2_inode_file && - q.block_type != gfs2_inode_lnk && q.block_type != gfs2_inode_blk && - q.block_type != gfs2_inode_chr && q.block_type != gfs2_inode_fifo && - q.block_type != gfs2_inode_sock) { + if(q != gfs2_inode_dir && q != gfs2_inode_file && + q != gfs2_inode_lnk && q != gfs2_inode_blk && + q != gfs2_inode_chr && q != gfs2_inode_fifo && + q != gfs2_inode_sock) { log_err( _("Directory entry '%s' at block %llu (0x%llx" ") in dir inode %llu (0x%llx" ") block type %d: %s.\n"), tmp_name, @@ -277,7 +274,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, (unsigned long long)de->de_inum.no_addr, (unsigned long long)ip->i_di.di_num.no_addr, (unsigned long long)ip->i_di.di_num.no_addr, - q.block_type, q.block_type == gfs2_meta_inval ? + q, q == gfs2_meta_inval ? _("previously marked invalid") : _("is not an inode")); @@ -291,7 +288,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, /* If it was previously marked invalid (i.e. known to be bad, not just a free block, etc.) then delete any metadata it holds. If not, return. */ - if (q.block_type != gfs2_meta_inval) + if (q != gfs2_meta_inval) return 1; /* Now try to clear the dinode, if it is an dinode */ @@ -319,7 +316,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, } } - error = check_file_type(de->de_type, q.block_type); + error = check_file_type(de->de_type, q); if(error < 0) { stack; return -1; @@ -330,7 +327,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, de_type_string(de->de_type), tmp_name, (unsigned long long)de->de_inum.no_addr, (unsigned long long)de->de_inum.no_addr, - block_type_string(&q)); + block_type_string(q)); if(query( _("Clear stale directory entry? (y/n) "))) { entry_ip = fsck_load_inode(sbp, de->de_inum.no_addr); check_inode_eattr(entry_ip, &clear_eattrs); @@ -446,7 +443,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, } } - if(q.block_type != gfs2_inode_dir) { + if(q != gfs2_inode_dir) { log_err( _("Found '..' entry in directory %llu (0x%llx) " "pointing to something that's not a directory"), (unsigned long long)ip->i_di.di_num.no_addr, @@ -487,7 +484,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, /* After this point we're only concerned with * directories */ - if(q.block_type != gfs2_inode_dir) { + if(q != gfs2_inode_dir) { log_debug( _("Found non-dir inode dentry\n")); increment_link(sbp, de->de_inum.no_addr); (*count)++; @@ -553,12 +550,10 @@ static int check_system_dir(struct gfs2_inode *sysinode, const char *dirname, if (sysinode) { iblock = sysinode->i_di.di_num.no_addr; - if(gfs2_block_check(sysinode->i_sbd, bl, iblock, &ds.q)) { - iblock = sysinode->i_di.di_num.no_addr; - } + ds.q = block_type(iblock); } pass2_fxns.private = (void *) &ds; - if(ds.q.block_type == gfs2_bad_block) { + if(ds.q == gfs2_bad_block) { /* First check that the directory's metatree is valid */ if(check_metatree(sysinode, &pass2_fxns)) { stack; @@ -656,7 +651,7 @@ static inline int is_system_dir(struct gfs2_sbd *sbp, uint64_t block) int pass2(struct gfs2_sbd *sbp) { uint64_t i; - struct gfs2_block_query q; + uint8_t q; struct dir_status ds = {0}; struct gfs2_inode *ip; char *filename; @@ -693,13 +688,9 @@ int pass2(struct gfs2_sbd *sbp) if (is_system_dir(sbp, i)) continue; - if(gfs2_block_check(sbp, bl, i, &q)) { - log_err( _("Can't get block %"PRIu64 " (0x%" PRIx64 - ") from block list\n"), i, i); - return FSCK_ERROR; - } + q = block_type(i); - if(q.block_type != gfs2_inode_dir) + if(q != gfs2_inode_dir) continue; log_debug( _("Checking directory inode at block %"PRIu64" (0x%" @@ -707,7 +698,7 @@ int pass2(struct gfs2_sbd *sbp) memset(&ds, 0, sizeof(ds)); pass2_fxns.private = (void *) &ds; - if(ds.q.block_type == gfs2_bad_block) { + if(ds.q == gfs2_bad_block) { /* First check that the directory's metatree * is valid */ ip = fsck_load_inode(sbp, i); diff --git a/gfs2/fsck/pass3.c b/gfs2/fsck/pass3.c index 2b9a3ef..bcca68c 100644 --- a/gfs2/fsck/pass3.c +++ b/gfs2/fsck/pass3.c @@ -12,6 +12,7 @@ #include "lost_n_found.h" #include "link.h" #include "metawalk.h" +#include "util.h" static int attach_dotdot_to(struct gfs2_sbd *sbp, uint64_t newdotdot, uint64_t olddotdot, uint64_t block) @@ -61,7 +62,7 @@ static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sbp, struct dir_info *di) { struct dir_info *pdi; - struct gfs2_block_query q_dotdot, q_treewalk; + uint8_t q_dotdot, q_treewalk; di->checked = 1; @@ -75,19 +76,8 @@ static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sbp, PRIu64" (0x%" PRIx64 ")\n"), di->dotdot_parent, di->dotdot_parent, di->treewalk_parent, di->treewalk_parent); - if(gfs2_block_check(sbp, bl, di->dotdot_parent, &q_dotdot)) { - log_err( _("Unable to find block %"PRIu64 - " (0x%" PRIx64 ") in block map.\n"), - di->dotdot_parent, di->dotdot_parent); - return NULL; - } - if(gfs2_block_check(sbp, bl, di->treewalk_parent, - &q_treewalk)) { - log_err( _("Unable to find block %"PRIu64 - " (0x%" PRIx64 ") in block map\n"), - di->treewalk_parent, di->treewalk_parent); - return NULL; - } + q_dotdot = block_type(di->dotdot_parent); + q_treewalk = block_type(di->treewalk_parent); /* if the dotdot entry isn't a directory, but the * treewalk is, treewalk is correct - if the treewalk * entry isn't a directory, but the dotdot is, dotdot @@ -95,8 +85,8 @@ static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sbp, * choose? if neither are directories, we have a * problem - need to move this directory into lost+found */ - if(q_dotdot.block_type != gfs2_inode_dir) { - if(q_treewalk.block_type != gfs2_inode_dir) { + if(q_dotdot != gfs2_inode_dir) { + if(q_treewalk != gfs2_inode_dir) { log_err( _("Orphaned directory, move to lost+found\n")); return NULL; } @@ -110,7 +100,7 @@ static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sbp, } } else { - if(q_treewalk.block_type != gfs2_inode_dir) { + if(q_treewalk != gfs2_inode_dir) { int error = 0; log_warn( _(".. parent is valid, but treewalk" "is bad - reattaching to lost+found")); @@ -152,13 +142,8 @@ static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sbp, } } else { - if(gfs2_block_check(sbp, bl, di->dotdot_parent, &q_dotdot)) { - log_err( _("Unable to find parent block %"PRIu64 - " (0x%" PRIx64 ") in block map\n"), - di->dotdot_parent, di->dotdot_parent); - return NULL; - } - if(q_dotdot.block_type != gfs2_inode_dir) { + q_dotdot = block_type(di->dotdot_parent); + if(q_dotdot != gfs2_inode_dir) { log_err( _("Orphaned directory at block %" PRIu64 " (0x%" PRIx64 ") moved to lost+found\n"), di->dinode, di->dinode); return NULL; @@ -180,7 +165,7 @@ int pass3(struct gfs2_sbd *sbp) osi_list_t *tmp; struct dir_info *di, *tdi; struct gfs2_inode *ip; - struct gfs2_block_query q; + uint8_t q; int i; find_di(sbp, sbp->md.rooti->i_di.di_num.no_addr, &di); @@ -212,11 +197,8 @@ int pass3(struct gfs2_sbd *sbp) /* FIXME: Factor this ? */ if(!tdi) { - if(gfs2_block_check(sbp, bl, di->dinode, &q)) { - stack; - return FSCK_ERROR; - } - if(q.block_type == gfs2_bad_block) { + q = block_type(di->dinode); + if(q == gfs2_bad_block) { log_err( _("Found unlinked directory containing bad block\n")); if(query( _("Clear unlinked directory with bad blocks? (y/n) "))) { @@ -227,13 +209,13 @@ int pass3(struct gfs2_sbd *sbp) } else log_err( _("Unlinked directory with bad block remains\n")); } - if(q.block_type != gfs2_inode_dir && - q.block_type != gfs2_inode_file && - q.block_type != gfs2_inode_lnk && - q.block_type != gfs2_inode_blk && - q.block_type != gfs2_inode_chr && - q.block_type != gfs2_inode_fifo && - q.block_type != gfs2_inode_sock) { + if(q != gfs2_inode_dir && + q != gfs2_inode_file && + q != gfs2_inode_lnk && + q != gfs2_inode_blk && + q != gfs2_inode_chr && + q != gfs2_inode_fifo && + q != gfs2_inode_sock) { log_err( _("Unlinked block marked as inode not an inode\n")); gfs2_blockmap_set(sbp, bl, di->dinode, gfs2_block_free); diff --git a/gfs2/fsck/pass4.c b/gfs2/fsck/pass4.c index 2bc64b5..b3f28d7 100644 --- a/gfs2/fsck/pass4.c +++ b/gfs2/fsck/pass4.c @@ -9,6 +9,7 @@ #include "lost_n_found.h" #include "inode_hash.h" #include "metawalk.h" +#include "util.h" struct metawalk_fxns pass4_fxns_delete = { .private = NULL, @@ -43,7 +44,7 @@ static int scan_inode_list(struct gfs2_sbd *sbp, osi_list_t *list) { struct inode_info *ii; struct gfs2_inode *ip; int lf_addition = 0; - struct gfs2_block_query q; + uint8_t q; /* FIXME: should probably factor this out into a generic * scanning fxn */ @@ -59,11 +60,8 @@ static int scan_inode_list(struct gfs2_sbd *sbp, osi_list_t *list) { if(ii->counted_links == 0) { log_err( _("Found unlinked inode at %" PRIu64 " (0x%" PRIx64 ")\n"), ii->inode, ii->inode); - if(gfs2_block_check(sbp, bl, ii->inode, &q)) { - stack; - return -1; - } - if(q.block_type == gfs2_bad_block) { + q = block_type(ii->inode); + if(q == gfs2_bad_block) { log_err( _("Unlinked inode %llu (0x%llx) contains" "bad blocks\n"), (unsigned long long)ii->inode, @@ -82,16 +80,15 @@ static int scan_inode_list(struct gfs2_sbd *sbp, osi_list_t *list) { } else log_err( _("Unlinked inode with bad blocks not cleared\n")); } - if(q.block_type != gfs2_inode_dir && - q.block_type != gfs2_inode_file && - q.block_type != gfs2_inode_lnk && - q.block_type != gfs2_inode_blk && - q.block_type != gfs2_inode_chr && - q.block_type != gfs2_inode_fifo && - q.block_type != gfs2_inode_sock) { + if(q != gfs2_inode_dir && + q != gfs2_inode_file && + q != gfs2_inode_lnk && + q != gfs2_inode_blk && + q != gfs2_inode_chr && + q != gfs2_inode_fifo && + q != gfs2_inode_sock) { log_err( _("Unlinked block marked as inode is " - "not an inode (%d)\n"), - q.block_type); + "not an inode (%d)\n"), q); ip = fsck_load_inode(sbp, ii->inode); if(query(_("Delete unlinked inode? (y/n) "))) { check_inode_eattr(ip, diff --git a/gfs2/fsck/pass5.c b/gfs2/fsck/pass5.c index f0d5911..3448204 100644 --- a/gfs2/fsck/pass5.c +++ b/gfs2/fsck/pass5.c @@ -10,9 +10,9 @@ #include "fs_bits.h" #include "util.h" -static int convert_mark(struct gfs2_block_query *q, uint32_t *count) +static int convert_mark(uint8_t q, uint32_t *count) { - switch(q->block_type) { + switch(q) { case gfs2_meta_inval: /* Convert invalid metadata to free blocks */ @@ -43,7 +43,7 @@ static int convert_mark(struct gfs2_block_query *q, uint32_t *count) return GFS2_BLKST_USED; default: - log_err( _("Invalid state %d found\n"), q->block_type); + log_err( _("Invalid state %d found\n"), q); return -1; } return -1; @@ -55,7 +55,7 @@ static int check_block_status(struct gfs2_sbd *sbp, char *buffer, unsigned int b unsigned char *byte, *end; unsigned int bit; unsigned char rg_status, block_status; - struct gfs2_block_query q; + uint8_t q; uint64_t block; static int free_unlinked = -1; @@ -70,9 +70,9 @@ static int check_block_status(struct gfs2_sbd *sbp, char *buffer, unsigned int b warm_fuzzy_stuff(block); if (skip_this_pass || fsck_abort) /* if asked to skip the rest */ return 0; - gfs2_block_check(sbp, bl, block, &q); + q = block_type(block); - block_status = convert_mark(&q, count); + block_status = convert_mark(q, count); /* If one node opens a file and another node deletes it, we may be left with a block that appears to be "unlinked" in @@ -119,8 +119,8 @@ static int check_block_status(struct gfs2_sbd *sbp, char *buffer, unsigned int b log_err( _("Ondisk status is %u (%s) but FSCK thinks it should be "), rg_status, blockstatus[rg_status]); log_err("%u (%s)\n", block_status, blockstatus[block_status]); - log_err( _("Metadata type is %u (%s)\n"), q.block_type, - block_type_string(&q)); + log_err( _("Metadata type is %u (%s)\n"), q, + block_type_string(q)); if(query( _("Fix bitmap for block %" PRIu64 " (0x%" PRIx64 ") ? (y/n) "), diff --git a/gfs2/fsck/util.c b/gfs2/fsck/util.c index 08eb831..2d601ef 100644 --- a/gfs2/fsck/util.c +++ b/gfs2/fsck/util.c @@ -79,15 +79,15 @@ void warm_fuzzy_stuff(uint64_t block) } } -const char *block_type_string(struct gfs2_block_query *q) +const char *block_type_string(uint8_t q) { const char *blktyp[] = {"free", "used", "indirect data", "inode", "file", "symlink", "block dev", "char dev", "fifo", "socket", "dir leaf", "journ data", "other meta", "eattribute", "unused", "invalid"}; - if (q->block_type < 16) - return (blktyp[q->block_type]); + if (q < 16) + return (blktyp[q]); return blktyp[15]; } diff --git a/gfs2/fsck/util.h b/gfs2/fsck/util.h index 5e5f96e..e3ff7e3 100644 --- a/gfs2/fsck/util.h +++ b/gfs2/fsck/util.h @@ -1,6 +1,7 @@ #ifndef __UTIL_H__ #define __UTIL_H__ +#include "fsck.h" #include "libgfs2.h" #define fsck_lseek(fd, off) \ @@ -9,7 +10,19 @@ struct di_info *search_list(osi_list_t *list, uint64_t addr); void big_file_comfort(struct gfs2_inode *ip, uint64_t blks_checked); void warm_fuzzy_stuff(uint64_t block); -const char *block_type_string(struct gfs2_block_query *q); +const char *block_type_string(uint8_t q); void gfs2_dup_set(uint64_t block); +static inline uint8_t block_type(uint64_t bblock) +{ + static unsigned char *byte; + static uint64_t b; + static uint8_t btype; + + byte = bl->map + BLOCKMAP_SIZE4(bblock); + b = BLOCKMAP_BYTE_OFFSET4(bblock); + btype = (*byte & (BLOCKMAP_MASK4 << b )) >> b; + return btype; +} + #endif /* __UTIL_H__ */ diff --git a/gfs2/libgfs2/block_list.c b/gfs2/libgfs2/block_list.c index e76217b..aa774be 100644 --- a/gfs2/libgfs2/block_list.c +++ b/gfs2/libgfs2/block_list.c @@ -137,21 +137,6 @@ int gfs2_blockmap_set(struct gfs2_sbd *sdp, struct gfs2_bmap *bmap, return 0; } -int gfs2_block_check(struct gfs2_sbd *sdp, struct gfs2_bmap *il, - uint64_t block, struct gfs2_block_query *val) -{ - static unsigned char *byte; - static uint64_t b; - - if(block >= il->size) - return -1; - - byte = il->map + BLOCKMAP_SIZE4(block); - b = BLOCKMAP_BYTE_OFFSET4(block); - val->block_type = (*byte & (BLOCKMAP_MASK4 << b )) >> b; - return 0; -} - void *gfs2_bmap_destroy(struct gfs2_sbd *sdp, struct gfs2_bmap *il) { if(il) { diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h index 035193f..3b843e5 100644 --- a/gfs2/libgfs2/libgfs2.h +++ b/gfs2/libgfs2/libgfs2.h @@ -300,10 +300,6 @@ enum gfs2_mark_block { gfs2_meta_inval = INVALID_META, }; -struct gfs2_block_query { - uint8_t block_type; -}; - extern struct gfs2_bmap *gfs2_bmap_create(struct gfs2_sbd *sdp, uint64_t size, uint64_t *addl_mem_needed); extern struct special_blocks *blockfind(struct special_blocks *blist, uint64_t num); @@ -319,8 +315,6 @@ extern int gfs2_block_unmark(struct gfs2_sbd *sdp, struct gfs2_bmap *il, /* gfs2_block_clear clears all the marks for the given block */ extern int gfs2_blockmap_clear(struct gfs2_sbd *sdp, struct gfs2_bmap *il, uint64_t block); -extern int gfs2_block_check(struct gfs2_sbd *sdp, struct gfs2_bmap *il, - uint64_t block, struct gfs2_block_query *val); extern void *gfs2_bmap_destroy(struct gfs2_sbd *sdp, struct gfs2_bmap *il); /* buf.c */
1
0
0
0
cluster: STABLE3 - Move duplicate code from libgfs2 to fsck.gfs2
by Bob Peterson
26 Jan '10
26 Jan '10
Gitweb:
http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=2f…
Commit: 2f222faced71bb3a90d1ed9d1dd4af3bede7eaf6 Parent: 327ce87f9acba792daf2729140b7f2ab6b0b3636 Author: Bob Peterson <bob(a)ganesha.peterson> AuthorDate: Wed Jan 20 09:47:30 2010 -0600 Committer: Bob Peterson <rpeterso(a)redhat.com> CommitterDate: Tue Jan 26 14:39:28 2010 -0600 Move duplicate code from libgfs2 to fsck.gfs2 This patch removes the duplicate block management from libgfs2 and puts it into the only code that used it: fsck.gfs2. This has several advantages for performance and readability. Since it no longer has to worry about duplicates, the blockmap code in libgfs2 can do less work in places where fsck.gfs2 doesn't care one way or another if the block is a duplicate. Conversely, the places in fsck.gfs2 that only care if the block is a duplicate are also simplified because they don't have to do the additional blockmap code that went along. This also paves the way for future code simplification. rhbz#455300 --- gfs2/fsck/eattr.c | 10 +---- gfs2/fsck/fsck.h | 7 +++ gfs2/fsck/initialize.c | 18 ++++++++- gfs2/fsck/main.c | 1 + gfs2/fsck/metawalk.c | 16 +++++++- gfs2/fsck/metawalk.h | 3 + gfs2/fsck/pass1.c | 31 ++++++-------- gfs2/fsck/pass1b.c | 24 +++++----- gfs2/fsck/pass2.c | 8 ++-- gfs2/fsck/util.c | 17 ++++++++ gfs2/fsck/util.h | 1 + gfs2/libgfs2/block_list.c | 100 ++++----------------------------------------- gfs2/libgfs2/libgfs2.h | 11 ----- 13 files changed, 100 insertions(+), 147 deletions(-) diff --git a/gfs2/fsck/eattr.c b/gfs2/fsck/eattr.c index 10e5636..a319500 100644 --- a/gfs2/fsck/eattr.c +++ b/gfs2/fsck/eattr.c @@ -6,17 +6,11 @@ #include "libgfs2.h" #include "fsck.h" #include "eattr.h" +#include "metawalk.h" static int clear_blk_nodup(struct gfs2_sbd *sbp, uint64_t block) { - struct gfs2_block_query q; - - if(gfs2_block_check(sbp, bl, block, &q)) { - stack; - return -1; - } - - if(q.dup_block) { + if(is_duplicate(block)) { log_debug( _("Not clearing block with marked as a duplicate\n")); return 1; } diff --git a/gfs2/fsck/fsck.h b/gfs2/fsck/fsck.h index 15c33f9..05a1147 100644 --- a/gfs2/fsck/fsck.h +++ b/gfs2/fsck/fsck.h @@ -59,6 +59,12 @@ enum rgindex_trust_level { /* how far can we trust our RG index? */ gfs2_grow or something. Count the RGs by hand. */ }; +struct dup_blks { + osi_list_t list; + uint64_t block_no; + osi_list_t ref_inode_list; +}; + extern struct gfs2_inode *fsck_load_inode(struct gfs2_sbd *sbp, uint64_t block); extern struct gfs2_inode *fsck_inode_get(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh); @@ -93,5 +99,6 @@ extern int skip_this_pass, fsck_abort; extern int errors_found, errors_corrected; extern uint64_t last_data_block; extern uint64_t first_data_block; +extern struct dup_blks dup_blocks; #endif /* _FSCK_H */ diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c index ec9c3cc..79f88fd 100644 --- a/gfs2/fsck/initialize.c +++ b/gfs2/fsck/initialize.c @@ -55,6 +55,19 @@ static int block_mounters(struct gfs2_sbd *sbp, int block_em) return 0; } +static void gfs2_dup_free(void) +{ + struct dup_blks *f; + + while(!osi_list_empty(&dup_blocks.list)) { + f = osi_list_entry(dup_blocks.list.next, struct dup_blks, + list); + while (!osi_list_empty(&f->ref_inode_list)) + osi_list_del(&f->ref_inode_list); + osi_list_del(&f->list); + free(f); + } +} /* * empty_super_block - free all structures in the super block @@ -87,8 +100,10 @@ static void empty_super_block(struct gfs2_sbd *sdp) } } - if (bl) + if (bl) { gfs2_bmap_destroy(sdp, bl); + gfs2_dup_free(); + } } @@ -380,6 +395,7 @@ static int init_system_inodes(struct gfs2_sbd *sdp) log_crit( _("Please increase your swap space by that amount and run gfs2_fsck again.\n")); goto fail; } + osi_list_init(&dup_blocks.list); return 0; fail: empty_super_block(sdp); diff --git a/gfs2/fsck/main.c b/gfs2/fsck/main.c index 195958c..34cc045 100644 --- a/gfs2/fsck/main.c +++ b/gfs2/fsck/main.c @@ -29,6 +29,7 @@ const char *pass = ""; uint64_t last_data_block; uint64_t first_data_block; int preen = 0, force_check = 0; +struct dup_blks dup_blocks; /* This function is for libgfs2's sake. */ void print_it(const char *label, const char *fmt, const char *fmt2, ...) diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c index 1f48e0a..aaa1144 100644 --- a/gfs2/fsck/metawalk.c +++ b/gfs2/fsck/metawalk.c @@ -16,6 +16,20 @@ #define COMFORTABLE_BLKS 5242880 /* 20GB in 4K blocks */ +struct dup_blks *dupfind(uint64_t num) +{ + osi_list_t *head = &dup_blocks.list; + osi_list_t *tmp; + struct dup_blks *b; + + for (tmp = head->next; tmp != head; tmp = tmp->next) { + b = osi_list_entry(tmp, struct dup_blks, list); + if (b->block_no == num) + return b; + } + return NULL; +} + static struct gfs2_inode *get_system_inode(struct gfs2_sbd *sbp, uint64_t block) { @@ -1184,7 +1198,7 @@ int delete_blocks(struct gfs2_inode *ip, uint64_t block, if (gfs2_check_range(ip->i_sbd, block) == 0) { if (gfs2_block_check(ip->i_sbd, bl, block, &q)) return 0; - if (!q.dup_block) { + if(!is_duplicate(block)) { log_info( _("Deleting %s block %lld (0x%llx) as part " "of inode %lld (0x%llx)\n"), btype, (unsigned long long)block, diff --git a/gfs2/fsck/metawalk.h b/gfs2/fsck/metawalk.h index b720516..0ad0aa2 100644 --- a/gfs2/fsck/metawalk.h +++ b/gfs2/fsck/metawalk.h @@ -25,6 +25,9 @@ int delete_eattr_indir(struct gfs2_inode *ip, uint64_t block, uint64_t parent, struct gfs2_buffer_head **bh, void *private); int delete_eattr_leaf(struct gfs2_inode *ip, uint64_t block, uint64_t parent, struct gfs2_buffer_head **bh, void *private); +struct dup_blks *dupfind(uint64_t num); + +#define is_duplicate(dblock) ((dupfind(dblock)) ? 1 : 0) /* metawalk_fxns: function pointers to check various parts of the fs * diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c index b284e56..5baf351 100644 --- a/gfs2/fsck/pass1.c +++ b/gfs2/fsck/pass1.c @@ -104,7 +104,7 @@ static int check_metalist(struct gfs2_inode *ip, uint64_t block, if(q.block_type != gfs2_block_free) { log_err( _("Found duplicate block referenced as metadata in " "indirect block - was marked %d\n"), q.block_type); - gfs2_block_mark(ip->i_sbd, bl, block, gfs2_dup_block); + gfs2_dup_set(block); found_dup = 1; } nbh = bread(ip->i_sbd, block); @@ -160,7 +160,7 @@ static int check_data(struct gfs2_inode *ip, uint64_t block, void *private) log_err( _("Found duplicate block referenced as data at %" PRIu64 " (0x%"PRIx64 ")\n"), block, block); if (q.block_type != gfs2_meta_inval) { - gfs2_block_mark(ip->i_sbd, bl, block, gfs2_dup_block); + gfs2_dup_set(block); /* If the prev ref was as data, this is likely a data block, so keep the block count for both refs. */ if (q.block_type == gfs2_block_used) @@ -178,11 +178,11 @@ static int check_data(struct gfs2_inode *ip, uint64_t block, void *private) marked as duplicate, but also as a data block. */ error = 1; gfs2_block_unmark(ip->i_sbd, bl, block, gfs2_meta_inval); - gfs2_block_mark(ip->i_sbd, bl, block, gfs2_dup_block); + gfs2_dup_set(block); } log_debug( _("Marking block %llu (0x%llx) as data block\n"), (unsigned long long)block, (unsigned long long)block); - gfs2_block_mark(ip->i_sbd, bl, block, gfs2_block_used); + gfs2_blockmap_set(ip->i_sbd, bl, block, gfs2_block_used); /* This is also confusing, so I'll clarify. There are two bitmaps: (1) The gfs2_bmap that fsck uses to keep track of what block @@ -245,12 +245,12 @@ static int ask_remove_inode_eattr(struct gfs2_inode *ip, if (query( _("Clear all Extended Attributes from the " "inode? (y/n) "))) { struct gfs2_block_query q; - if(gfs2_block_check(ip->i_sbd, bl, ip->i_di.di_eattr, &q)) { stack; return -1; } - if (!remove_inode_eattr(ip, bc, q.dup_block)) + if (!remove_inode_eattr(ip, bc, + is_duplicate(ip->i_di.di_eattr))) log_err( _("Extended attributes were removed.\n")); else log_err( _("Unable to remove inode eattr pointer; " @@ -333,8 +333,7 @@ static int check_eattr_indir(struct gfs2_inode *ip, uint64_t indirect, if (!clear_eas(ip, bc, indirect, 1, _("Bad indirect Extended Attribute " "duplicate found"))) { - gfs2_block_mark(sdp, bl, indirect, - gfs2_dup_block); + gfs2_dup_set(indirect); bc->ea_count++; } return 1; @@ -352,7 +351,7 @@ static int check_eattr_indir(struct gfs2_inode *ip, uint64_t indirect, (unsigned long long)ip->i_di.di_num.no_addr, (unsigned long long)indirect, (unsigned long long)indirect); - gfs2_block_mark(sdp, bl, indirect, gfs2_dup_block); + gfs2_dup_set(indirect); bc->ea_count++; ret = 1; } else { @@ -428,7 +427,7 @@ static int check_leaf_block(struct gfs2_inode *ip, uint64_t block, int btype, log_debug( _("Duplicate block found at #%lld (0x%llx).\n"), (unsigned long long)block, (unsigned long long)block); - gfs2_block_mark(sdp, bl, block, gfs2_dup_block); + gfs2_dup_set(block); bc->ea_count++; brelse(leaf_bh); return 1; @@ -576,7 +575,7 @@ static int clear_metalist(struct gfs2_inode *ip, uint64_t block, stack; return -1; } - if(!q.dup_block) { + if(!is_duplicate(block)) { gfs2_blockmap_set(ip->i_sbd, bl, block, gfs2_block_free); return 0; } @@ -591,7 +590,7 @@ static int clear_data(struct gfs2_inode *ip, uint64_t block, void *private) stack; return -1; } - if(!q.dup_block) { + if(!is_duplicate(block)) { gfs2_blockmap_set(ip->i_sbd, bl, block, gfs2_block_free); return 0; } @@ -611,7 +610,7 @@ static int clear_leaf(struct gfs2_inode *ip, uint64_t block, stack; return -1; } - if(!q.dup_block) { + if(!is_duplicate(block)) { log_crit( _("Setting leaf #%" PRIu64 " (0x%" PRIx64 ") invalid\n"), block, block); if(gfs2_blockmap_set(ip->i_sbd, bl, block, gfs2_block_free)) { @@ -692,11 +691,7 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh, if(q.block_type != gfs2_block_free) { log_err( _("Found duplicate block referenced as an inode at " "#%" PRIu64 " (0x%" PRIx64 ")\n"), block, block); - if(gfs2_block_mark(sdp, bl, block, gfs2_dup_block)) { - stack; - fsck_inode_put(&ip); - return -1; - } + gfs2_dup_set(block); fsck_inode_put(&ip); return 0; } diff --git a/gfs2/fsck/pass1b.c b/gfs2/fsck/pass1b.c index 26e8f63..a25e4da 100644 --- a/gfs2/fsck/pass1b.c +++ b/gfs2/fsck/pass1b.c @@ -28,7 +28,7 @@ struct fxn_info { }; struct dup_handler { - struct dup_blocks *b; + struct dup_blks *b; struct inode_with_dups *id; int ref_inode_count; int ref_count; @@ -113,12 +113,12 @@ static int find_dentry(struct gfs2_inode *ip, struct gfs2_dirent *de, uint16_t *count, void *priv) { osi_list_t *tmp1, *tmp2; - struct dup_blocks *b; + struct dup_blks *b; struct inode_with_dups *id; struct gfs2_leaf leaf; - osi_list_foreach(tmp1, &ip->i_sbd->dup_blocks.list) { - b = osi_list_entry(tmp1, struct dup_blocks, list); + osi_list_foreach(tmp1, &dup_blocks.list) { + b = osi_list_entry(tmp1, struct dup_blks, list); osi_list_foreach(tmp2, &b->ref_inode_list) { id = osi_list_entry(tmp2, struct inode_with_dups, list); @@ -313,7 +313,7 @@ static int clear_eattr_extentry(struct gfs2_inode *ip, uint64_t *ea_data_ptr, } /* Finds all references to duplicate blocks in the metadata */ -static int find_block_ref(struct gfs2_sbd *sbp, uint64_t inode, struct dup_blocks *b) +static int find_block_ref(struct gfs2_sbd *sbp, uint64_t inode, struct dup_blks *b) { struct gfs2_inode *ip; struct fxn_info myfi = {b->block_no, 0, 1}; @@ -367,7 +367,7 @@ static int find_block_ref(struct gfs2_sbd *sbp, uint64_t inode, struct dup_block return 0; } -static int handle_dup_blk(struct gfs2_sbd *sbp, struct dup_blocks *b) +static int handle_dup_blk(struct gfs2_sbd *sbp, struct dup_blks *b) { osi_list_t *tmp; struct inode_with_dups *id; @@ -492,7 +492,7 @@ static int handle_dup_blk(struct gfs2_sbd *sbp, struct dup_blocks *b) * use in pass2 */ int pass1b(struct gfs2_sbd *sbp) { - struct dup_blocks *b; + struct dup_blks *b; uint64_t i; struct gfs2_block_query q; osi_list_t *tmp = NULL, *x; @@ -503,7 +503,7 @@ int pass1b(struct gfs2_sbd *sbp) log_info( _("Looking for duplicate blocks...\n")); /* If there were no dups in the bitmap, we don't need to do anymore */ - if(osi_list_empty(&sbp->dup_blocks.list)) { + if(osi_list_empty(&dup_blocks.list)) { log_info( _("No duplicate blocks found\n")); return FSCK_OK; } @@ -531,8 +531,8 @@ int pass1b(struct gfs2_sbd *sbp) (q.block_type == gfs2_inode_chr) || (q.block_type == gfs2_inode_fifo) || (q.block_type == gfs2_inode_sock)) { - osi_list_foreach_safe(tmp, &sbp->dup_blocks.list, x) { - b = osi_list_entry(tmp, struct dup_blocks, + osi_list_foreach_safe(tmp, &dup_blocks.list, x) { + b = osi_list_entry(tmp, struct dup_blks, list); if(find_block_ref(sbp, i, b)) { stack; @@ -550,8 +550,8 @@ int pass1b(struct gfs2_sbd *sbp) * it later */ log_info( _("Handling duplicate blocks\n")); out: - osi_list_foreach_safe(tmp, &sbp->dup_blocks.list, x) { - b = osi_list_entry(tmp, struct dup_blocks, list); + osi_list_foreach_safe(tmp, &dup_blocks.list, x) { + b = osi_list_entry(tmp, struct dup_blks, list); if (!skip_this_pass && !rc) /* no error & not asked to skip the rest */ handle_dup_blk(sbp, b); } diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c index 4858c2f..7453e47 100644 --- a/gfs2/fsck/pass2.c +++ b/gfs2/fsck/pass2.c @@ -663,7 +663,7 @@ int pass2(struct gfs2_sbd *sbp) int filename_len; char tmp_name[256]; int error = 0; - struct dup_blocks *b; + struct dup_blks *b; /* Check all the system directory inodes. */ if (check_system_dir(sbp->md.jiinode, "jindex", build_jindex)) { @@ -809,9 +809,9 @@ int pass2(struct gfs2_sbd *sbp) deleting it from both inodes referencing it. Note: The other returns from this function are premature exits of the program and gfs2_block_list_destroy should get rid of the list for us. */ - while (!osi_list_empty(&sbp->dup_blocks.list)) { - b = osi_list_entry(sbp->dup_blocks.list.next, - struct dup_blocks, list); + while (!osi_list_empty(&dup_blocks.list)) { + b = osi_list_entry(dup_blocks.list.next, + struct dup_blks, list); osi_list_del(&b->list); free(b); } diff --git a/gfs2/fsck/util.c b/gfs2/fsck/util.c index 3159720..08eb831 100644 --- a/gfs2/fsck/util.c +++ b/gfs2/fsck/util.c @@ -10,6 +10,7 @@ #include "libgfs2.h" #include "fs_bits.h" +#include "metawalk.h" #include "util.h" void big_file_comfort(struct gfs2_inode *ip, uint64_t blks_checked) @@ -149,3 +150,19 @@ int fsck_query(const char *format, ...) opts.query = FALSE; return ret; } + +void gfs2_dup_set(uint64_t block) +{ + struct dup_blks *b; + + if (dupfind(block)) + return; + b = malloc(sizeof(struct dup_blks)); + if (b) { + memset(b, 0, sizeof(*b)); + b->block_no = block; + osi_list_init(&b->ref_inode_list); + osi_list_add(&b->list, &dup_blocks.list); + } + return; +} diff --git a/gfs2/fsck/util.h b/gfs2/fsck/util.h index fa18506..5e5f96e 100644 --- a/gfs2/fsck/util.h +++ b/gfs2/fsck/util.h @@ -10,5 +10,6 @@ struct di_info *search_list(osi_list_t *list, uint64_t addr); void big_file_comfort(struct gfs2_inode *ip, uint64_t blks_checked); void warm_fuzzy_stuff(uint64_t block); const char *block_type_string(struct gfs2_block_query *q); +void gfs2_dup_set(uint64_t block); #endif /* __UTIL_H__ */ diff --git a/gfs2/libgfs2/block_list.c b/gfs2/libgfs2/block_list.c index 31cc530..e76217b 100644 --- a/gfs2/libgfs2/block_list.c +++ b/gfs2/libgfs2/block_list.c @@ -8,14 +8,6 @@ #include "libgfs2.h" -/* Must be kept in sync with mark_block enum in libgfs2.h */ -static int mark_to_gbmap[16] = { - FREE, BLOCK_IN_USE, DIR_INDIR_BLK, DIR_INODE, FILE_INODE, - LNK_INODE, BLK_INODE, CHR_INODE, FIFO_INODE, SOCK_INODE, - DIR_LEAF_INODE, JOURNAL_BLK, OTHER_META, EATTR_META, - BAD_BLOCK, INVALID_META -}; - static int gfs2_blockmap_create(struct gfs2_bmap *bmap, uint64_t size) { bmap->size = size; @@ -57,7 +49,6 @@ struct gfs2_bmap *gfs2_bmap_create(struct gfs2_sbd *sdp, uint64_t size, free(il); il = NULL; } - osi_list_init(&sdp->dup_blocks.list); osi_list_init(&sdp->eattr_blocks.list); return il; } @@ -74,19 +65,6 @@ void gfs2_special_free(struct special_blocks *blist) } } -static void gfs2_dup_free(struct dup_blocks *blist) -{ - struct dup_blocks *f; - - while(!osi_list_empty(&blist->list)) { - f = osi_list_entry(blist->list.next, struct dup_blocks, list); - while (!osi_list_empty(&f->ref_inode_list)) - osi_list_del(&f->ref_inode_list); - osi_list_del(&f->list); - free(f); - } -} - struct special_blocks *blockfind(struct special_blocks *blist, uint64_t num) { osi_list_t *head = &blist->list; @@ -101,20 +79,6 @@ struct special_blocks *blockfind(struct special_blocks *blist, uint64_t num) return NULL; } -static struct dup_blocks *dupfind(struct dup_blocks *blist, uint64_t num) -{ - osi_list_t *head = &blist->list; - osi_list_t *tmp; - struct dup_blocks *b; - - for (tmp = head->next; tmp != head; tmp = tmp->next) { - b = osi_list_entry(tmp, struct dup_blocks, list); - if (b->block_no == num) - return b; - } - return NULL; -} - void gfs2_special_set(struct special_blocks *blocklist, uint64_t block) { struct special_blocks *b; @@ -130,33 +94,6 @@ void gfs2_special_set(struct special_blocks *blocklist, uint64_t block) return; } -static void gfs2_dup_set(struct dup_blocks *blocklist, uint64_t block) -{ - struct dup_blocks *b; - - if (dupfind(blocklist, block)) - return; - b = malloc(sizeof(struct dup_blocks)); - if (b) { - memset(b, 0, sizeof(*b)); - b->block_no = block; - osi_list_init(&b->ref_inode_list); - osi_list_add(&b->list, &blocklist->list); - } - return; -} - -static void gfs2_dup_clear(struct dup_blocks *blocklist, uint64_t block) -{ - struct dup_blocks *b; - - b = dupfind(blocklist, block); - if (b) { - osi_list_del(&b->list); - free(b); - } -} - void gfs2_special_clear(struct special_blocks *blocklist, uint64_t block) { struct special_blocks *b; @@ -168,39 +105,20 @@ void gfs2_special_clear(struct special_blocks *blocklist, uint64_t block) } } -int gfs2_block_mark(struct gfs2_sbd *sdp, struct gfs2_bmap *il, - uint64_t block, enum gfs2_mark_block mark) -{ - int err = 0; - - if(mark == gfs2_dup_block) - gfs2_dup_set(&sdp->dup_blocks, block); - else - err = gfs2_blockmap_set(sdp, il, block, mark_to_gbmap[mark]); - return err; -} - /* gfs2_block_unmark clears ONE mark for the given block */ int gfs2_block_unmark(struct gfs2_sbd *sdp, struct gfs2_bmap *bmap, uint64_t block, enum gfs2_mark_block mark) { - int err = 0; - - if (mark == gfs2_dup_block) - gfs2_dup_clear(&sdp->dup_blocks, block); - else { - static unsigned char *byte; - static uint64_t b; + static unsigned char *byte; + static uint64_t b; - if(block > bmap->size) - return -1; + if(block > bmap->size) + return -1; - byte = bmap->map + BLOCKMAP_SIZE4(block); - b = BLOCKMAP_BYTE_OFFSET4(block); - *byte &= ~(BLOCKMAP_MASK4 << b); - return 0; - } - return err; + byte = bmap->map + BLOCKMAP_SIZE4(block); + b = BLOCKMAP_BYTE_OFFSET4(block); + *byte &= ~(BLOCKMAP_MASK4 << b); + return 0; } int gfs2_blockmap_set(struct gfs2_sbd *sdp, struct gfs2_bmap *bmap, @@ -228,7 +146,6 @@ int gfs2_block_check(struct gfs2_sbd *sdp, struct gfs2_bmap *il, if(block >= il->size) return -1; - val->dup_block = (dupfind(&sdp->dup_blocks, block) ? 1 : 0); byte = il->map + BLOCKMAP_SIZE4(block); b = BLOCKMAP_BYTE_OFFSET4(block); val->block_type = (*byte & (BLOCKMAP_MASK4 << b )) >> b; @@ -242,7 +159,6 @@ void *gfs2_bmap_destroy(struct gfs2_sbd *sdp, struct gfs2_bmap *il) free(il); il = NULL; } - gfs2_dup_free(&sdp->dup_blocks); gfs2_special_free(&sdp->eattr_blocks); return il; } diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h index 1d2d5e8..035193f 100644 --- a/gfs2/libgfs2/libgfs2.h +++ b/gfs2/libgfs2/libgfs2.h @@ -116,12 +116,6 @@ struct gfs2_buffer_head { struct gfs2_sbd *sdp; }; -struct dup_blocks { - osi_list_t list; - uint64_t block_no; - osi_list_t ref_inode_list; -}; - struct special_blocks { osi_list_t list; uint64_t block; @@ -240,7 +234,6 @@ struct gfs2_sbd { unsigned int writes; int metafs_fd; char metafs_path[PATH_MAX]; /* where metafs is mounted */ - struct dup_blocks dup_blocks; struct special_blocks eattr_blocks; }; @@ -305,12 +298,10 @@ enum gfs2_mark_block { gfs2_meta_eattr = EATTR_META, gfs2_bad_block = BAD_BLOCK, /* Contains at least one bad block */ gfs2_meta_inval = INVALID_META, - gfs2_dup_block, /* Contains at least one duplicate block */ }; struct gfs2_block_query { uint8_t block_type; - uint8_t dup_block; }; extern struct gfs2_bmap *gfs2_bmap_create(struct gfs2_sbd *sdp, uint64_t size, @@ -322,8 +313,6 @@ extern int gfs2_blockmap_set(struct gfs2_sbd *sdp, struct gfs2_bmap *il, uint64_t block, enum gfs2_mark_block mark); extern void gfs2_special_clear(struct special_blocks *blocklist, uint64_t block); -extern int gfs2_block_mark(struct gfs2_sbd *sdp, struct gfs2_bmap *il, - uint64_t block, enum gfs2_mark_block mark); /* gfs2_block_unmark clears ONE mark for the given block */ extern int gfs2_block_unmark(struct gfs2_sbd *sdp, struct gfs2_bmap *il, uint64_t block, enum gfs2_mark_block m);
1
0
0
0
cluster: STABLE3 - libgfs2: Consistent naming for blockmap functions
by Bob Peterson
26 Jan '10
26 Jan '10
Gitweb:
http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=32…
Commit: 327ce87f9acba792daf2729140b7f2ab6b0b3636 Parent: b78341e5b79195ccdc292b6f2ebf5b16cd559914 Author: Bob Peterson <bob(a)ganesha.peterson> AuthorDate: Tue Jan 19 18:00:45 2010 -0600 Committer: Bob Peterson <rpeterso(a)redhat.com> CommitterDate: Tue Jan 26 14:39:28 2010 -0600 libgfs2: Consistent naming for blockmap functions This patch provides for better consistency in naming of the functions that operate on the blockmap in memory. Before, there were functions like gfs2_bitmap_set and gfs2_set_bitmap but one operated on the rgrp bitmap and the other operated on the blockmap in memory. This patch makes the code more readable and understandable. It also paves the way for later simplification of blockmap querying and separating out the duplicate reference management for performance purposes. rhbz#455300 --- gfs2/edit/savemeta.c | 6 +- gfs2/fsck/eattr.c | 2 +- gfs2/fsck/lost_n_found.c | 2 +- gfs2/fsck/main.c | 4 +- gfs2/fsck/metawalk.c | 6 +- gfs2/fsck/pass1.c | 56 +++++++++++++------------- gfs2/fsck/pass1b.c | 12 +++--- gfs2/fsck/pass2.c | 10 ++-- gfs2/fsck/pass3.c | 6 +- gfs2/fsck/pass4.c | 6 +- gfs2/libgfs2/block_list.c | 96 ++++++++++++++++---------------------------- gfs2/libgfs2/libgfs2.h | 14 ++++-- 12 files changed, 99 insertions(+), 121 deletions(-) diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c index 1651a94..4b49050 100644 --- a/gfs2/edit/savemeta.c +++ b/gfs2/edit/savemeta.c @@ -642,9 +642,9 @@ void savemeta(char *out_fn, int saveoption) (unsigned long long)rgd->ri.ri_addr, rgd->ri.ri_length); for (i = 0; i < rgd->ri.ri_length; i++) { - if(gfs2_block_set(&sbd, blocklist, - rgd->ri.ri_addr + i, - gfs2_meta_other)) + if(gfs2_blockmap_set(&sbd, blocklist, + rgd->ri.ri_addr + i, + gfs2_meta_other)) break; } first = 1; diff --git a/gfs2/fsck/eattr.c b/gfs2/fsck/eattr.c index 6194244..10e5636 100644 --- a/gfs2/fsck/eattr.c +++ b/gfs2/fsck/eattr.c @@ -21,7 +21,7 @@ static int clear_blk_nodup(struct gfs2_sbd *sbp, uint64_t block) return 1; } - gfs2_block_set(sbp, bl, block, gfs2_block_free); + gfs2_blockmap_set(sbp, bl, block, gfs2_block_free); return 0; diff --git a/gfs2/fsck/lost_n_found.c b/gfs2/fsck/lost_n_found.c index cc2ba14..ffa88b2 100644 --- a/gfs2/fsck/lost_n_found.c +++ b/gfs2/fsck/lost_n_found.c @@ -47,7 +47,7 @@ int add_inode_to_lf(struct gfs2_inode *ip){ * directory or just found an old one, and we * used that instead of the block_type to run * this */ - gfs2_block_set(ip->i_sbd, bl, + gfs2_blockmap_set(ip->i_sbd, bl, lf_dip->i_di.di_num.no_addr, gfs2_inode_dir); increment_link(ip->i_sbd, ip->i_sbd->md.rooti->i_di.di_num.no_addr); diff --git a/gfs2/fsck/main.c b/gfs2/fsck/main.c index ffd7530..195958c 100644 --- a/gfs2/fsck/main.c +++ b/gfs2/fsck/main.c @@ -172,7 +172,7 @@ static int check_system_inode(struct gfs2_inode *sysinode, const char *filename, /* Just reuse the inode and fix the bitmap. */ if (ds.q.block_type == gfs2_block_free) { log_info( _("The inode exists but the block is not marked 'in use'; fixing it.\n")); - gfs2_block_set(sysinode->i_sbd, bl, + gfs2_blockmap_set(sysinode->i_sbd, bl, sysinode->i_di.di_num.no_addr, mark); ds.q.block_type = mark; @@ -191,7 +191,7 @@ static int check_system_inode(struct gfs2_inode *sysinode, const char *filename, log_err( _("Invalid or missing %s system inode.\n"), filename); if (query(_("Create new %s system inode? (y/n) "), filename)) { builder(sysinode->i_sbd); - gfs2_block_set(sysinode->i_sbd, bl, + gfs2_blockmap_set(sysinode->i_sbd, bl, sysinode->i_di.di_num.no_addr, mark); ds.q.block_type = mark; diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c index 75ad1e7..1f48e0a 100644 --- a/gfs2/fsck/metawalk.c +++ b/gfs2/fsck/metawalk.c @@ -596,7 +596,7 @@ static int check_eattr_entries(struct gfs2_inode *ip, /* Endianness doesn't matter in this case because it's a single byte. */ - gfs2_block_set(sdp, bl, + gfs2_blockmap_set(sdp, bl, ip->i_di.di_eattr, gfs2_meta_eattr); log_err( _("The EA was " @@ -750,7 +750,7 @@ static int check_indirect_eattr(struct gfs2_inode *ip, uint64_t indirect, if (indirect_buf->b_changed) gfs2_set_bitmap(sdp, indirect, GFS2_BLKST_FREE); - gfs2_block_set(sdp, bl, indirect, + gfs2_blockmap_set(sdp, bl, indirect, gfs2_block_free); error = 1; } @@ -1191,7 +1191,7 @@ int delete_blocks(struct gfs2_inode *ip, uint64_t 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); - gfs2_block_set(ip->i_sbd, bl, block, gfs2_block_free); + gfs2_blockmap_set(ip->i_sbd, bl, block, gfs2_block_free); gfs2_free_block(ip->i_sbd, block); } } diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c index ca36e8d..b284e56 100644 --- a/gfs2/fsck/pass1.c +++ b/gfs2/fsck/pass1.c @@ -75,7 +75,7 @@ static int leaf(struct gfs2_inode *ip, uint64_t block, log_debug( _("\tLeaf block at %15" PRIu64 " (0x%" PRIx64 ")\n"), block, block); - gfs2_block_set(ip->i_sbd, bl, block, gfs2_leaf_blk); + gfs2_blockmap_set(ip->i_sbd, bl, block, gfs2_leaf_blk); bc->indir_count++; return 0; } @@ -91,7 +91,7 @@ static int check_metalist(struct gfs2_inode *ip, uint64_t block, *bh = NULL; if (gfs2_check_range(ip->i_sbd, block)){ /* blk outside of FS */ - gfs2_block_set(ip->i_sbd, bl, ip->i_di.di_num.no_addr, + gfs2_blockmap_set(ip->i_sbd, bl, ip->i_di.di_num.no_addr, gfs2_bad_block); log_debug( _("Bad indirect block pointer (out of range).\n")); @@ -113,7 +113,7 @@ static int check_metalist(struct gfs2_inode *ip, uint64_t block, log_debug( _("Bad indirect block pointer (points to " "something that is not an indirect block).\n")); if(!found_dup) { - gfs2_block_set(ip->i_sbd, bl, block, gfs2_meta_inval); + gfs2_blockmap_set(ip->i_sbd, bl, block, gfs2_meta_inval); brelse(nbh); return 1; } @@ -124,7 +124,7 @@ static int check_metalist(struct gfs2_inode *ip, uint64_t block, if (!found_dup) { log_debug( _("Setting %" PRIu64 " (0x%" PRIx64 ") to indirect " "block.\n"), block, block); - gfs2_block_set(ip->i_sbd, bl, block, gfs2_indir_blk); + gfs2_blockmap_set(ip->i_sbd, bl, block, gfs2_indir_blk); } bc->indir_count++; @@ -146,7 +146,7 @@ static int check_data(struct gfs2_inode *ip, uint64_t block, void *private) /* Mark the owner of this block with the bad_block * designator so we know to check it for out of range * blocks later */ - gfs2_block_set(ip->i_sbd, bl, ip->i_di.di_num.no_addr, + gfs2_blockmap_set(ip->i_sbd, bl, ip->i_di.di_num.no_addr, gfs2_bad_block); return 1; } @@ -187,7 +187,7 @@ static int check_data(struct gfs2_inode *ip, uint64_t block, void *private) /* This is also confusing, so I'll clarify. There are two bitmaps: (1) The gfs2_bmap that fsck uses to keep track of what block type has been discovered, and (2) The rgrp bitmap. Function - gfs2_block_set is used to set the former and gfs2_set_bitmap + gfs2_blockmap_set is used to set the former and gfs2_set_bitmap is used to set the latter. In this function we need to set both because we found a "data" block that could be "meta" in the rgrp bitmap. If we don't we could run into the data block again as @@ -225,7 +225,7 @@ static int remove_inode_eattr(struct gfs2_inode *ip, struct block_count *bc, if (!duplicate) { gfs2_set_bitmap(ip->i_sbd, ip->i_di.di_eattr, GFS2_BLKST_FREE); - gfs2_block_set(ip->i_sbd, bl, ip->i_di.di_eattr, + gfs2_blockmap_set(ip->i_sbd, bl, ip->i_di.di_eattr, gfs2_block_free); } ip->i_di.di_eattr = 0; @@ -286,7 +286,7 @@ static int clear_eas(struct gfs2_inode *ip, struct block_count *bc, log_err( _("The bad extended attribute was " "removed.\n")); } else if (!duplicate) { - gfs2_block_set(sdp, bl, block, gfs2_block_free); + gfs2_blockmap_set(sdp, bl, block, gfs2_block_free); gfs2_set_bitmap(sdp, block, GFS2_BLKST_FREE); log_err( _("The bad Extended Attribute was " "removed.\n")); @@ -313,7 +313,7 @@ static int check_eattr_indir(struct gfs2_inode *ip, uint64_t indirect, if(gfs2_check_range(sdp, indirect)) { /*log_warn("EA indirect block #%"PRIu64" is out of range.\n", indirect); - gfs2_block_set(sdp, bl, parent, bad_block);*/ + gfs2_blockmap_set(sdp, bl, parent, bad_block);*/ /* Doesn't help to mark this here - this gets checked * in pass1c */ return 1; @@ -359,7 +359,7 @@ static int check_eattr_indir(struct gfs2_inode *ip, uint64_t indirect, log_debug( _("Setting #%" PRIu64 " (0x%" PRIx64 ") to indirect Extended Attribute block\n"), indirect, indirect); - gfs2_block_set(sdp, bl, indirect, gfs2_indir_blk); + gfs2_blockmap_set(sdp, bl, indirect, gfs2_indir_blk); bc->ea_count++; } return ret; @@ -449,7 +449,7 @@ static int check_leaf_block(struct gfs2_inode *ip, uint64_t block, int btype, /* Point of confusion: We've got to set the ea block itself to gfs2_meta_eattr here. Elsewhere we mark the inode with gfs2_eattr_block meaning it contains an eattr for pass1c. */ - gfs2_block_set(sdp, bl, block, gfs2_meta_eattr); + gfs2_blockmap_set(sdp, bl, block, gfs2_meta_eattr); bc->ea_count++; *bh = leaf_bh; return 0; @@ -487,7 +487,7 @@ static int check_extended_leaf_eattr(struct gfs2_inode *ip, uint64_t *data_ptr, (unsigned long long)ip->i_di.di_eattr, (unsigned long long)el_blk, (unsigned long long)el_blk); - gfs2_block_set(sdp, bl, ip->i_di.di_eattr, gfs2_bad_block); + gfs2_blockmap_set(sdp, bl, ip->i_di.di_eattr, gfs2_bad_block); return 1; } error = check_leaf_block(ip, el_blk, GFS2_METATYPE_ED, &bh, private); @@ -518,7 +518,7 @@ static int check_eattr_leaf(struct gfs2_inode *ip, uint64_t block, (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); - gfs2_block_set(sdp, bl, ip->i_di.di_eattr, gfs2_bad_block); + gfs2_blockmap_set(sdp, bl, ip->i_di.di_eattr, gfs2_bad_block); return 1; } return check_leaf_block(ip, block, GFS2_METATYPE_EA, bh, private); @@ -577,7 +577,7 @@ static int clear_metalist(struct gfs2_inode *ip, uint64_t block, return -1; } if(!q.dup_block) { - gfs2_block_set(ip->i_sbd, bl, block, gfs2_block_free); + gfs2_blockmap_set(ip->i_sbd, bl, block, gfs2_block_free); return 0; } return 0; @@ -592,7 +592,7 @@ static int clear_data(struct gfs2_inode *ip, uint64_t block, void *private) return -1; } if(!q.dup_block) { - gfs2_block_set(ip->i_sbd, bl, block, gfs2_block_free); + gfs2_blockmap_set(ip->i_sbd, bl, block, gfs2_block_free); return 0; } return 0; @@ -614,7 +614,7 @@ static int clear_leaf(struct gfs2_inode *ip, uint64_t block, if(!q.dup_block) { log_crit( _("Setting leaf #%" PRIu64 " (0x%" PRIx64 ") invalid\n"), block, block); - if(gfs2_block_set(ip->i_sbd, bl, block, gfs2_block_free)) { + if(gfs2_blockmap_set(ip->i_sbd, bl, block, gfs2_block_free)) { stack; return -1; } @@ -706,7 +706,7 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh, case S_IFDIR: log_debug( _("Setting %" PRIu64 " (0x%" PRIx64 ") to directory inode.\n"), block, block); - if(gfs2_block_set(sdp, bl, block, gfs2_inode_dir)) { + if(gfs2_blockmap_set(sdp, bl, block, gfs2_inode_dir)) { stack; fsck_inode_put(&ip); return -1; @@ -720,7 +720,7 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh, case S_IFREG: log_debug( _("Setting %" PRIu64 " (0x%" PRIx64 ") to file inode.\n"), block, block); - if(gfs2_block_set(sdp, bl, block, gfs2_inode_file)) { + if(gfs2_blockmap_set(sdp, bl, block, gfs2_inode_file)) { stack; fsck_inode_put(&ip); return -1; @@ -729,7 +729,7 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh, case S_IFLNK: log_debug( _("Setting %" PRIu64 " (0x%" PRIx64 ") to symlink inode.\n"), block, block); - if(gfs2_block_set(sdp, bl, block, gfs2_inode_lnk)) { + if(gfs2_blockmap_set(sdp, bl, block, gfs2_inode_lnk)) { stack; fsck_inode_put(&ip); return -1; @@ -738,7 +738,7 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh, case S_IFBLK: log_debug( _("Setting %" PRIu64 " (0x%" PRIx64 ") to block dev inode.\n"), block, block); - if(gfs2_block_set(sdp, bl, block, gfs2_inode_blk)) { + if(gfs2_blockmap_set(sdp, bl, block, gfs2_inode_blk)) { stack; fsck_inode_put(&ip); return -1; @@ -747,7 +747,7 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh, case S_IFCHR: log_debug( _("Setting %" PRIu64 " (0x%" PRIx64 ") to char dev inode.\n"), block, block); - if(gfs2_block_set(sdp, bl, block, gfs2_inode_chr)) { + if(gfs2_blockmap_set(sdp, bl, block, gfs2_inode_chr)) { stack; fsck_inode_put(&ip); return -1; @@ -756,7 +756,7 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh, case S_IFIFO: log_debug( _("Setting %" PRIu64 " (0x%" PRIx64 ") to fifo inode.\n"), block, block); - if(gfs2_block_set(sdp, bl, block, gfs2_inode_fifo)) { + if(gfs2_blockmap_set(sdp, bl, block, gfs2_inode_fifo)) { stack; fsck_inode_put(&ip); return -1; @@ -765,7 +765,7 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh, case S_IFSOCK: log_debug( _("Setting %" PRIu64 " (0x%" PRIx64 ") to socket inode.\n"), block, block); - if(gfs2_block_set(sdp, bl, block, gfs2_inode_sock)) { + if(gfs2_blockmap_set(sdp, bl, block, gfs2_inode_sock)) { stack; fsck_inode_put(&ip); return -1; @@ -774,7 +774,7 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh, default: log_debug( _("Setting %" PRIu64 " (0x%" PRIx64 ") to invalid.\n"), block, block); - if(gfs2_block_set(sdp, bl, block, gfs2_meta_inval)) { + if(gfs2_blockmap_set(sdp, bl, block, gfs2_meta_inval)) { stack; fsck_inode_put(&ip); return -1; @@ -800,7 +800,7 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh, (1 >> (ip->i_di.di_size/sizeof(uint64_t)))); /* once implemented, remove continue statement */ log_warn( _("Marking inode invalid\n")); - if(gfs2_block_set(sdp, bl, block, gfs2_meta_inval)) { + if(gfs2_blockmap_set(sdp, bl, block, gfs2_meta_inval)) { stack; fsck_inode_put(&ip); return -1; @@ -824,7 +824,7 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh, (unsigned long long)ip->i_di.di_num.no_addr); /* FIXME: Must set all leaves invalid as well */ check_metatree(ip, &invalidate_metatree); - gfs2_block_set(sdp, bl, ip->i_di.di_num.no_addr, + gfs2_blockmap_set(sdp, bl, ip->i_di.di_num.no_addr, gfs2_meta_inval); gfs2_set_bitmap(sdp, ip->i_di.di_num.no_addr, GFS2_BLKST_FREE); fsck_inode_put(&ip); @@ -875,7 +875,7 @@ static int scan_meta(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh, log_info( _("Found invalid metadata at #%llu (0x%llx)\n"), (unsigned long long)block, (unsigned long long)block); - if(gfs2_block_set(sdp, bl, block, gfs2_meta_inval)) { + if(gfs2_blockmap_set(sdp, bl, block, gfs2_meta_inval)) { stack; return -1; } @@ -955,7 +955,7 @@ int pass1(struct gfs2_sbd *sbp) rg_count); rgd = osi_list_entry(tmp, struct rgrp_list, list); for (i = 0; i < rgd->ri.ri_length; i++) { - if(gfs2_block_set(sbp, bl, rgd->ri.ri_addr + i, + if(gfs2_blockmap_set(sbp, bl, rgd->ri.ri_addr + i, gfs2_meta_other)){ stack; return FSCK_ERROR; diff --git a/gfs2/fsck/pass1b.c b/gfs2/fsck/pass1b.c index 3d093ad..26e8f63 100644 --- a/gfs2/fsck/pass1b.c +++ b/gfs2/fsck/pass1b.c @@ -174,7 +174,7 @@ static int clear_dup_metalist(struct gfs2_inode *ip, uint64_t block, inode_hash_remove(inode_hash, ip->i_di.di_num.no_addr); /* Setting the block to invalid means the inode is * cleared in pass2 */ - gfs2_block_set(ip->i_sbd, bl, ip->i_di.di_num.no_addr, + gfs2_blockmap_set(ip->i_sbd, bl, ip->i_di.di_num.no_addr, gfs2_meta_inval); } return 0; @@ -206,7 +206,7 @@ static int clear_dup_eattr_indir(struct gfs2_inode *ip, uint64_t block, log_err( _("Inode %s is in directory %" PRIu64 " (0x%" PRIx64 ")\n"), dh->id->name ? dh->id->name : "", dh->id->parent, dh->id->parent); - gfs2_block_set(ip->i_sbd, bl, ip->i_di.di_eattr, + gfs2_blockmap_set(ip->i_sbd, bl, ip->i_di.di_eattr, gfs2_meta_inval); } @@ -233,7 +233,7 @@ static int clear_dup_eattr_leaf(struct gfs2_inode *ip, uint64_t block, dh->id->name ? dh->id->name : "", dh->id->parent, dh->id->parent); /* mark the main eattr block invalid */ - gfs2_block_set(ip->i_sbd, bl, ip->i_di.di_eattr, + gfs2_blockmap_set(ip->i_sbd, bl, ip->i_di.di_eattr, gfs2_meta_inval); } @@ -304,7 +304,7 @@ static int clear_eattr_extentry(struct gfs2_inode *ip, uint64_t *ea_data_ptr, dh->id->name ? dh->id->name : "", dh->id->parent, dh->id->parent); /* mark the main eattr block invalid */ - gfs2_block_set(ip->i_sbd, bl, ip->i_di.di_eattr, + gfs2_blockmap_set(ip->i_sbd, bl, ip->i_di.di_eattr, gfs2_meta_inval); } @@ -424,7 +424,7 @@ static int handle_dup_blk(struct gfs2_sbd *sbp, struct dup_blocks *b) ip->i_di.di_num.no_addr); /* Setting the block to invalid means the inode is cleared in pass2 */ - gfs2_block_set(ip->i_sbd, bl, + gfs2_blockmap_set(ip->i_sbd, bl, ip->i_di.di_num.no_addr, gfs2_meta_inval); bmodified(ip->i_bh); @@ -472,7 +472,7 @@ static int handle_dup_blk(struct gfs2_sbd *sbp, struct dup_blocks *b) if(!id->ea_only) check_metatree(ip, &clear_dup_fxns); - gfs2_block_set(ip->i_sbd, bl, ip->i_di.di_num.no_addr, + gfs2_blockmap_set(ip->i_sbd, bl, ip->i_di.di_num.no_addr, gfs2_meta_inval); fsck_inode_put(&ip); /* out, brelse, free */ dh.ref_inode_count--; diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c index 147fd12..4858c2f 100644 --- a/gfs2/fsck/pass2.c +++ b/gfs2/fsck/pass2.c @@ -184,7 +184,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, "\tName length = %u\n"), de->de_rec_len, de->de_name_len); - gfs2_block_set(sbp, bl, ip->i_di.di_num.no_addr, + gfs2_blockmap_set(sbp, bl, ip->i_di.di_num.no_addr, gfs2_meta_inval); return 1; /* FIXME: should probably delete the entry here at the @@ -252,7 +252,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, bmodified(entry_ip->i_bh); fsck_inode_put(&entry_ip); dirent2_del(ip, bh, prev_de, dent); - gfs2_block_set(sbp, bl, de->de_inum.no_addr, + gfs2_blockmap_set(sbp, bl, de->de_inum.no_addr, gfs2_block_free); bmodified(bh); log_warn( _("The inode containing bad blocks was " @@ -307,7 +307,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, check_metatree(entry_ip, &pass2_fxns_delete); bmodified(entry_ip->i_bh); fsck_inode_put(&entry_ip); - gfs2_block_set(sbp, bl, de->de_inum.no_addr, + gfs2_blockmap_set(sbp, bl, de->de_inum.no_addr, gfs2_block_free); return 1; @@ -571,7 +571,7 @@ static int check_system_dir(struct gfs2_inode *sysinode, const char *dirname, return -1; } if (error > 0) - gfs2_block_set(sysinode->i_sbd, bl, iblock, gfs2_meta_inval); + gfs2_blockmap_set(sysinode->i_sbd, bl, iblock, gfs2_meta_inval); if(check_inode_eattr(sysinode, &pass2_fxns)) { stack; @@ -751,7 +751,7 @@ int pass2(struct gfs2_sbd *sbp) } else log_err( _("Directory entry to invalid inode remains.\n")); } - gfs2_block_set(sbp, bl, i, gfs2_meta_inval); + gfs2_blockmap_set(sbp, bl, i, gfs2_meta_inval); } ip = fsck_load_inode(sbp, i); if(!ds.dotdir) { diff --git a/gfs2/fsck/pass3.c b/gfs2/fsck/pass3.c index 807ced2..2b9a3ef 100644 --- a/gfs2/fsck/pass3.c +++ b/gfs2/fsck/pass3.c @@ -220,7 +220,7 @@ int pass3(struct gfs2_sbd *sbp) log_err( _("Found unlinked directory containing bad block\n")); if(query( _("Clear unlinked directory with bad blocks? (y/n) "))) { - gfs2_block_set(sbp, bl, + gfs2_blockmap_set(sbp, bl, di->dinode, gfs2_block_free); break; @@ -235,7 +235,7 @@ int pass3(struct gfs2_sbd *sbp) q.block_type != gfs2_inode_fifo && q.block_type != gfs2_inode_sock) { log_err( _("Unlinked block marked as inode not an inode\n")); - gfs2_block_set(sbp, bl, di->dinode, + gfs2_blockmap_set(sbp, bl, di->dinode, gfs2_block_free); log_err( _("Cleared\n")); break; @@ -249,7 +249,7 @@ int pass3(struct gfs2_sbd *sbp) if(!ip->i_di.di_size && !ip->i_di.di_eattr){ log_err( _("Unlinked directory has zero size.\n")); if(query( _("Remove zero-size unlinked directory? (y/n) "))) { - gfs2_block_set(sbp, bl, + gfs2_blockmap_set(sbp, bl, di->dinode, gfs2_block_free); fsck_inode_put(&ip); diff --git a/gfs2/fsck/pass4.c b/gfs2/fsck/pass4.c index 6389342..2bc64b5 100644 --- a/gfs2/fsck/pass4.c +++ b/gfs2/fsck/pass4.c @@ -76,7 +76,7 @@ static int scan_inode_list(struct gfs2_sbd *sbp, osi_list_t *list) { check_metatree(ip, &pass4_fxns_delete); bmodified(ip->i_bh); fsck_inode_put(&ip); - gfs2_block_set(sbp, bl, ii->inode, + gfs2_blockmap_set(sbp, bl, ii->inode, gfs2_block_free); continue; } else @@ -98,7 +98,7 @@ static int scan_inode_list(struct gfs2_sbd *sbp, osi_list_t *list) { &pass4_fxns_delete); check_metatree(ip, &pass4_fxns_delete); bmodified(ip->i_bh); - gfs2_block_set(sbp, bl, ii->inode, + gfs2_blockmap_set(sbp, bl, ii->inode, gfs2_block_free); log_err( _("The inode was deleted\n")); } else { @@ -116,7 +116,7 @@ static int scan_inode_list(struct gfs2_sbd *sbp, osi_list_t *list) { if(!ip->i_di.di_size && !ip->i_di.di_eattr){ log_err( _("Unlinked inode has zero size\n")); if(query( _("Clear zero-size unlinked inode? (y/n) "))) { - gfs2_block_set(sbp, bl, ii->inode, + gfs2_blockmap_set(sbp, bl, ii->inode, gfs2_block_free); fsck_inode_put(&ip); continue; diff --git a/gfs2/libgfs2/block_list.c b/gfs2/libgfs2/block_list.c index 569c1e2..31cc530 100644 --- a/gfs2/libgfs2/block_list.c +++ b/gfs2/libgfs2/block_list.c @@ -16,17 +16,13 @@ static int mark_to_gbmap[16] = { BAD_BLOCK, INVALID_META }; -#define BITMAP_SIZE4(size) (size >> 1) -#define BITMAP_BYTE_OFFSET4(x) ((x & 0x0000000000000001) << 2) -#define BITMAP_MASK4 (0xf) - -static int gfs2_bitmap_create(struct gfs2_bmap *bmap, uint64_t size) +static int gfs2_blockmap_create(struct gfs2_bmap *bmap, uint64_t size) { bmap->size = size; - /* Have to add 1 to BITMAP_SIZE since it's 0-based and mallocs + /* Have to add 1 to BLOCKMAP_SIZE since it's 0-based and mallocs * must be 1-based */ - bmap->mapsize = BITMAP_SIZE4(size); + bmap->mapsize = BLOCKMAP_SIZE4(size); if(!(bmap->map = malloc(sizeof(char) * bmap->mapsize))) return -ENOMEM; @@ -38,36 +34,7 @@ static int gfs2_bitmap_create(struct gfs2_bmap *bmap, uint64_t size) return 0; } -static int gfs2_bitmap_set(struct gfs2_bmap *bmap, uint64_t offset, uint8_t val) -{ - static char *byte; - static uint64_t b; - - if(offset < bmap->size) { - byte = bmap->map + BITMAP_SIZE4(offset); - b = BITMAP_BYTE_OFFSET4(offset); - *byte |= (val & BITMAP_MASK4) << b; - return 0; - } - return -1; -} - -static int gfs2_bitmap_clear(struct gfs2_bmap *bmap, uint64_t offset) -{ - static char *byte; - static uint64_t b; - - if(offset < bmap->size) { - byte = bmap->map + BITMAP_SIZE4(offset); - b = BITMAP_BYTE_OFFSET4(offset); - *byte &= ~(BITMAP_MASK4 << b); - return 0; - } - return -1; - -} - -static void gfs2_bitmap_destroy(struct gfs2_bmap *bmap) +static void gfs2_blockmap_destroy(struct gfs2_bmap *bmap) { if(bmap->map) free(bmap->map); @@ -85,7 +52,7 @@ struct gfs2_bmap *gfs2_bmap_create(struct gfs2_sbd *sdp, uint64_t size, if (!il || !memset(il, 0, sizeof(*il))) return NULL; - if(gfs2_bitmap_create(il, size)) { + if(gfs2_blockmap_create(il, size)) { *addl_mem_needed = il->mapsize; free(il); il = NULL; @@ -209,62 +176,69 @@ int gfs2_block_mark(struct gfs2_sbd *sdp, struct gfs2_bmap *il, if(mark == gfs2_dup_block) gfs2_dup_set(&sdp->dup_blocks, block); else - err = gfs2_bitmap_set(il, block, mark_to_gbmap[mark]); + err = gfs2_blockmap_set(sdp, il, block, mark_to_gbmap[mark]); return err; } /* gfs2_block_unmark clears ONE mark for the given block */ -int gfs2_block_unmark(struct gfs2_sbd *sdp, struct gfs2_bmap *il, +int gfs2_block_unmark(struct gfs2_sbd *sdp, struct gfs2_bmap *bmap, uint64_t block, enum gfs2_mark_block mark) { int err = 0; if (mark == gfs2_dup_block) gfs2_dup_clear(&sdp->dup_blocks, block); - else - err = gfs2_bitmap_clear(il, block); + else { + static unsigned char *byte; + static uint64_t b; + + if(block > bmap->size) + return -1; + + byte = bmap->map + BLOCKMAP_SIZE4(block); + b = BLOCKMAP_BYTE_OFFSET4(block); + *byte &= ~(BLOCKMAP_MASK4 << b); + return 0; + } return err; } -/* gfs2_block_clear clears all the marks for the given block */ -int gfs2_block_clear(struct gfs2_sbd *sdp, struct gfs2_bmap *il, - uint64_t block) +int gfs2_blockmap_set(struct gfs2_sbd *sdp, struct gfs2_bmap *bmap, + uint64_t bblock, enum gfs2_mark_block mark) { - gfs2_dup_clear(&sdp->dup_blocks, block); - return gfs2_bitmap_clear(il, block); -} + static unsigned char *byte; + static uint64_t b; -int gfs2_block_set(struct gfs2_sbd *sdp, struct gfs2_bmap *il, - uint64_t block, enum gfs2_mark_block mark) -{ - int err; + if(bblock > bmap->size) + return -1; - err = gfs2_block_clear(sdp, il, block); /* clear all block status */ - if(!err) - err = gfs2_block_mark(sdp, il, block, mark); - return err; + byte = bmap->map + BLOCKMAP_SIZE4(bblock); + b = BLOCKMAP_BYTE_OFFSET4(bblock); + *byte &= ~(BLOCKMAP_MASK4 << b); + *byte |= (mark & BLOCKMAP_MASK4) << b; + return 0; } int gfs2_block_check(struct gfs2_sbd *sdp, struct gfs2_bmap *il, uint64_t block, struct gfs2_block_query *val) { - static char *byte; + static unsigned char *byte; static uint64_t b; if(block >= il->size) return -1; val->dup_block = (dupfind(&sdp->dup_blocks, block) ? 1 : 0); - byte = il->map + BITMAP_SIZE4(block); - b = BITMAP_BYTE_OFFSET4(block); - val->block_type = (*byte & (BITMAP_MASK4 << b )) >> b; + byte = il->map + BLOCKMAP_SIZE4(block); + b = BLOCKMAP_BYTE_OFFSET4(block); + val->block_type = (*byte & (BLOCKMAP_MASK4 << b )) >> b; return 0; } void *gfs2_bmap_destroy(struct gfs2_sbd *sdp, struct gfs2_bmap *il) { if(il) { - gfs2_bitmap_destroy(il); + gfs2_blockmap_destroy(il); free(il); il = NULL; } diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h index db1b38e..1d2d5e8 100644 --- a/gfs2/libgfs2/libgfs2.h +++ b/gfs2/libgfs2/libgfs2.h @@ -69,6 +69,10 @@ __BEGIN_DECLS #endif /* __BYTE_ORDER == __LITTLE_ENDIAN */ +#define BLOCKMAP_SIZE4(size) (size >> 1) +#define BLOCKMAP_BYTE_OFFSET4(x) ((x & 0x0000000000000001) << 2) +#define BLOCKMAP_MASK4 (0xf) + static __inline__ __attribute__((noreturn, format (printf, 1, 2))) void die(const char *fmt, ...) { @@ -262,7 +266,7 @@ struct metapath { struct gfs2_bmap { uint64_t size; uint64_t mapsize; - char *map; + unsigned char *map; }; /* block_list.c */ @@ -314,17 +318,17 @@ extern struct gfs2_bmap *gfs2_bmap_create(struct gfs2_sbd *sdp, uint64_t size, extern struct special_blocks *blockfind(struct special_blocks *blist, uint64_t num); extern void gfs2_special_set(struct special_blocks *blocklist, uint64_t block); extern void gfs2_special_free(struct special_blocks *blist); -extern int gfs2_block_mark(struct gfs2_sbd *sdp, struct gfs2_bmap *il, - uint64_t block, enum gfs2_mark_block mark); -extern int gfs2_block_set(struct gfs2_sbd *sdp, struct gfs2_bmap *il, +extern int gfs2_blockmap_set(struct gfs2_sbd *sdp, struct gfs2_bmap *il, uint64_t block, enum gfs2_mark_block mark); extern void gfs2_special_clear(struct special_blocks *blocklist, uint64_t block); +extern int gfs2_block_mark(struct gfs2_sbd *sdp, struct gfs2_bmap *il, + uint64_t block, enum gfs2_mark_block mark); /* gfs2_block_unmark clears ONE mark for the given block */ extern int gfs2_block_unmark(struct gfs2_sbd *sdp, struct gfs2_bmap *il, uint64_t block, enum gfs2_mark_block m); /* gfs2_block_clear clears all the marks for the given block */ -extern int gfs2_block_clear(struct gfs2_sbd *sdp, struct gfs2_bmap *il, +extern int gfs2_blockmap_clear(struct gfs2_sbd *sdp, struct gfs2_bmap *il, uint64_t block); extern int gfs2_block_check(struct gfs2_sbd *sdp, struct gfs2_bmap *il, uint64_t block, struct gfs2_block_query *val);
1
0
0
0
cluster: STABLE3 - fsck.gfs2: Verify rgrps free space against bitmap
by Bob Peterson
26 Jan '10
26 Jan '10
Gitweb:
http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=b7…
Commit: b78341e5b79195ccdc292b6f2ebf5b16cd559914 Parent: a099128a0f504eca010cb7435a740830ce272153 Author: Bob Peterson <bob(a)ganesha.peterson> AuthorDate: Tue Jan 19 15:33:17 2010 -0600 Committer: Bob Peterson <rpeterso(a)redhat.com> CommitterDate: Tue Jan 26 14:39:28 2010 -0600 fsck.gfs2: Verify rgrps free space against bitmap This patch makes fsck.gfs2 check the actual bits in the rgrp bitmaps to see how many blocks are free. It verifies that value against the rg_free value in the rgrp. It needs to ensure that it starts with an accurate value for rg_free because an inaccurate value can get us into trouble and cause fsck.gfs2 to abort abnormally. This can happen in cases where it tries to allocate blocks (for example, for lost+found metadata) when the bitmaps say there is free space when there really isn't. rhbz#455300 --- gfs2/fsck/initialize.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 128 insertions(+), 0 deletions(-) diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c index 0844187..ec9c3cc 100644 --- a/gfs2/fsck/initialize.c +++ b/gfs2/fsck/initialize.c @@ -158,6 +158,132 @@ static int set_block_ranges(struct gfs2_sbd *sdp) } /** + * check_rgrp_integrity - verify a rgrp free block count against the bitmap + */ +static void check_rgrp_integrity(struct gfs2_sbd *sdp, struct rgrp_list *rgd, + int *fixit, int *this_rg_fixed, + int *this_rg_bad) +{ + uint32_t rg_free, rg_reclaimed; + int rgb, x, y, off, bytes_to_check, total_bytes_to_check; + unsigned int state; + + rg_free = rg_reclaimed = 0; + total_bytes_to_check = rgd->ri.ri_bitbytes; + *this_rg_fixed = *this_rg_bad = 0; + + for (rgb = 0; rgb < rgd->ri.ri_length; rgb++){ + /* Count up the free blocks in the bitmap */ + off = (rgb) ? sizeof(struct gfs2_meta_header) : + sizeof(struct gfs2_rgrp); + if (total_bytes_to_check <= sdp->bsize - off) + bytes_to_check = total_bytes_to_check; + else + bytes_to_check = sdp->bsize - off; + total_bytes_to_check -= bytes_to_check; + for (x = 0; x < bytes_to_check; x++) { + unsigned char *byte; + + byte = (unsigned char *)&rgd->bh[rgb]->b_data[off + x]; + if (*byte == 0x55) + continue; + if (*byte == 0x00) { + rg_free += GFS2_NBBY; + continue; + } + for (y = 0; y < GFS2_NBBY; y++) { + state = (*byte >> + (GFS2_BIT_SIZE * y)) & GFS2_BIT_MASK; + if (state == GFS2_BLKST_USED) + continue; + if (state == GFS2_BLKST_DINODE) + continue; + if (state == GFS2_BLKST_FREE) { + rg_free++; + continue; + } + /* GFS2_BLKST_UNLINKED */ + *this_rg_bad = 1; + if (!(*fixit)) { + if (query(_("Okay to reclaim unlinked " + "inodes? (y/n)"))) + *fixit = 1; + } + if (!(*fixit)) + continue; + *byte &= ~(GFS2_BIT_MASK << + (GFS2_BIT_SIZE * y)); + bmodified(rgd->bh[rgb]); + rg_reclaimed++; + rg_free++; + *this_rg_fixed = 1; + } + } + } + if (rgd->rg.rg_free != rg_free) { + *this_rg_bad = 1; + log_err( _("Error: resource group %lld (0x%llx): " + "free space (%d) does not match bitmap (%d)\n"), + (unsigned long long)rgd->ri.ri_addr, + (unsigned long long)rgd->ri.ri_addr, + rgd->rg.rg_free, rg_free); + if (rg_reclaimed) + log_err( _("(%d blocks were reclaimed)\n"), + rg_reclaimed); + if (query( _("Fix the rgrp free blocks count? (y/n)"))) { + rgd->rg.rg_free = rg_free; + gfs2_rgrp_out(&rgd->rg, rgd->bh[0]); + *this_rg_fixed = 1; + log_err( _("The rgrp was fixed.\n")); + } else + log_err( _("The rgrp was not fixed.\n")); + } + /* + else { + log_debug( _("Resource group %lld (0x%llx) free space " + "is consistent: free: %d reclaimed: %d\n"), + (unsigned long long)rgd->ri.ri_addr, + (unsigned long long)rgd->ri.ri_addr, + rg_free, rg_reclaimed); + }*/ +} + +/** + * check_rgrps_integrity - verify rgrp consistency + * + * Returns: 0 on success, 1 if errors were detected + */ +static int check_rgrps_integrity(struct gfs2_sbd *sdp) +{ + int rgs_good = 0, rgs_bad = 0, rgs_fixed = 0; + int was_bad = 0, was_fixed = 0, error = 0; + osi_list_t *tmp; + struct rgrp_list *rgd; + int reclaim_unlinked = 0; + + log_info( _("Checking the integrity of all resource groups.\n")); + for (tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next) { + if (fsck_abort) + return 0; + rgd = osi_list_entry(tmp, struct rgrp_list, list); + check_rgrp_integrity(sdp, rgd, &reclaim_unlinked, + &was_fixed, &was_bad); + if (was_fixed) + rgs_fixed++; + if (was_bad) { + error = 1; + rgs_bad++; + } else + rgs_good++; + } + if (rgs_bad) + log_err( _("RGs: Consistent: %d Inconsistent: %d Fixed: %d" + " Total: %d\n"), + rgs_good, rgs_bad, rgs_fixed, rgs_good + rgs_bad); + return error; +} + +/** * init_system_inodes * * Returns: 0 on success, -1 on failure @@ -235,6 +361,8 @@ static int init_system_inodes(struct gfs2_sbd *sdp) } log_info( _("%u resource groups found.\n"), rgcount); + check_rgrps_integrity(sdp); + /******************************************************************* ******* Now, set boundary fields in the super block ************* *******************************************************************/
1
0
0
0
← Newer
1
2
3
4
5
6
7
8
...
19
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Results per page:
10
25
50
100
200