gfs2-utils: master - GFS2: fsck.gfs2 segfault - osi_tree "each_safe" patch

Bob Peterson rpeterso at fedoraproject.org
Wed Mar 17 14:56:23 UTC 2010


Gitweb:        http://git.fedorahosted.org/git/gfs2-utils.git?p=gfs2-utils.git;a=commitdiff;h=4b29c515f2c2e22c55a6c3a0de0e219adbb6275a
Commit:        4b29c515f2c2e22c55a6c3a0de0e219adbb6275a
Parent:        3c4002c3101cb5e893295408fb819f77c285b6d0
Author:        Bob Peterson <rpeterso at redhat.com>
AuthorDate:    Wed Mar 17 09:46:09 2010 -0500
Committer:     Bob Peterson <rpeterso at redhat.com>
CommitterDate: Wed Mar 17 09:52:08 2010 -0500

GFS2: fsck.gfs2 segfault - osi_tree "each_safe" patch

There are a few places in fsck.gfs2 where each element of the
new rbtrees are processed.  Some of those places delete
items from the rbtree, which means I need to use the equivalent
of osi_list_foreach_safe.  In other words, I needed to prevent
rbtree deletes from interfering with the next() function.
The result was a segfault in fsck.gfs2 in a few places.  This
patch implements the "safe" rbtree traversal and fixes the problem.

rhbz#574215
---
 gfs2/fsck/link.c   |    2 --
 gfs2/fsck/pass1b.c |   10 ++++++----
 gfs2/fsck/pass3.c  |    5 +++--
 gfs2/fsck/pass4.c  |    5 +++--
 4 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/gfs2/fsck/link.c b/gfs2/fsck/link.c
index 0996fa9..9b518a8 100644
--- a/gfs2/fsck/link.c
+++ b/gfs2/fsck/link.c
@@ -69,8 +69,6 @@ int decrement_link(uint64_t inode_no, uint64_t referenced_from,
 	ii = inodetree_find(inode_no);
 	/* If the list has entries, look for one that matches
 	 * inode_no */
-	log_err( _("Decrementing %"PRIu64" (0x%" PRIx64 ") to %d\n"),
-		 inode_no, inode_no, ii->counted_links);
 	if(ii) {
 		ii->counted_links--;
 		log_debug( _("Directory %lld (0x%llx) decremented counted "
diff --git a/gfs2/fsck/pass1b.c b/gfs2/fsck/pass1b.c
index 29f98e0..c3290c2 100644
--- a/gfs2/fsck/pass1b.c
+++ b/gfs2/fsck/pass1b.c
@@ -170,12 +170,13 @@ static int find_dentry(struct gfs2_inode *ip, struct gfs2_dirent *de,
 		       struct gfs2_buffer_head *bh, char *filename,
 		       uint16_t *count, void *priv)
 {
-	struct osi_node *n;
+	struct osi_node *n, *next = NULL;
 	osi_list_t *tmp2;
 	struct duptree *b;
 	int found;
 
-	for (n = osi_first(&dup_blocks); n; n = osi_next(n)) {
+	for (n = osi_first(&dup_blocks); n; n = next) {
+		next = osi_next(n);
 		b = (struct duptree *)n;
 		found = 0;
 		osi_list_foreach(tmp2, &b->ref_invinode_list) {
@@ -602,7 +603,7 @@ int pass1b(struct gfs2_sbd *sbp)
 	struct duptree *b;
 	uint64_t i;
 	uint8_t q;
-	struct osi_node *n;
+	struct osi_node *n, *next = NULL;
 	int rc = FSCK_OK;
 
 	log_info( _("Looking for duplicate blocks...\n"));
@@ -652,7 +653,8 @@ int pass1b(struct gfs2_sbd *sbp)
 	 * it later */
 	log_info( _("Handling duplicate blocks\n"));
 out:
-        for (n = osi_first(&dup_blocks); n; n = osi_next(n)) {
+        for (n = osi_first(&dup_blocks); n; n = next) {
+		next = 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);
diff --git a/gfs2/fsck/pass3.c b/gfs2/fsck/pass3.c
index bd583df..50b15da 100644
--- a/gfs2/fsck/pass3.c
+++ b/gfs2/fsck/pass3.c
@@ -174,7 +174,7 @@ static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sbp,
  */
 int pass3(struct gfs2_sbd *sbp)
 {
-	struct osi_node *tmp;
+	struct osi_node *tmp, *next = NULL;
 	struct dir_info *di, *tdi;
 	struct gfs2_inode *ip;
 	uint8_t q;
@@ -195,7 +195,8 @@ int pass3(struct gfs2_sbd *sbp)
 	 * find a parent, put in lost+found.
 	 */
 	log_info( _("Checking directory linkage.\n"));
-	for (tmp = osi_first(&dirtree); tmp; tmp = osi_next(tmp)) {
+	for (tmp = osi_first(&dirtree); tmp; tmp = next) {
+		next = osi_next(tmp);
 		di = (struct dir_info *)tmp;
 		while(!di->checked) {
 			/* FIXME: Change this so it returns success or
diff --git a/gfs2/fsck/pass4.c b/gfs2/fsck/pass4.c
index 9db27d9..da98523 100644
--- a/gfs2/fsck/pass4.c
+++ b/gfs2/fsck/pass4.c
@@ -42,7 +42,7 @@ static int fix_link_count(struct inode_info *ii, struct gfs2_inode *ip)
 }
 
 static int scan_inode_list(struct gfs2_sbd *sbp) {
-	struct osi_node *tmp;
+	struct osi_node *tmp, *next = NULL;
 	struct inode_info *ii;
 	struct gfs2_inode *ip;
 	int lf_addition = 0;
@@ -50,9 +50,10 @@ static int scan_inode_list(struct gfs2_sbd *sbp) {
 
 	/* FIXME: should probably factor this out into a generic
 	 * scanning fxn */
-	for (tmp = osi_first(&inodetree); tmp; tmp = osi_next(tmp)) {
+	for (tmp = osi_first(&inodetree); tmp; tmp = next) {
 		if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
 			return 0;
+		next = osi_next(tmp);
 		if(!(ii = (struct inode_info *)tmp)) {
 			log_crit( _("osi_tree broken in scan_info_list!!\n"));
 			exit(FSCK_ERROR);


More information about the cluster-commits mailing list