public inbox for cluster-cvs@sourceware.org
help / color / mirror / Atom feed
* cluster: STABLE3 - Fix gfs2_fsck segfault
@ 2009-04-20 18:26 Bob Peterson
  0 siblings, 0 replies; only message in thread
From: Bob Peterson @ 2009-04-20 18:26 UTC (permalink / raw)
  To: cluster-cvs-relay

Gitweb:        http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=d1d0e689b40943c9d1964df13b94dbc88453e6ab
Commit:        d1d0e689b40943c9d1964df13b94dbc88453e6ab
Parent:        69dd1942d6d443003e6a66be5e9f5cb5bccce0e7
Author:        Bob Peterson <rpeterso@redhat.com>
AuthorDate:    Mon Apr 20 13:06:06 2009 -0500
Committer:     Bob Peterson <rpeterso@redhat.com>
CommitterDate: Mon Apr 20 13:06:06 2009 -0500

Fix gfs2_fsck segfault

bz 496330

The gfs2_fsck tool was segfaulting if gfs2 had any blocks
assigned to two different purposes.  There were two problems.
First, struct blocks was not big enough to handle the data
that pass1b needed for duplicate processing.  Second,
function pass1b() was improperly referencing the duplicate
blocks list.
---
 gfs2/fsck/pass1b.c        |   25 +++++++----------
 gfs2/libgfs2/block_list.c |   63 ++++++++++++++++++++++++++++++++++++++++++---
 gfs2/libgfs2/libgfs2.h    |    8 +++++-
 3 files changed, 76 insertions(+), 20 deletions(-)

diff --git a/gfs2/fsck/pass1b.c b/gfs2/fsck/pass1b.c
index bcef089..02a5f9b 100644
--- a/gfs2/fsck/pass1b.c
+++ b/gfs2/fsck/pass1b.c
@@ -19,12 +19,6 @@ struct inode_with_dups {
 	char *name;
 };
 
-struct blocks {
-	osi_list_t list;
-	uint64_t block_no;
-	osi_list_t ref_inode_list;
-};
-
 struct fxn_info {
 	uint64_t block;
 	int found;
@@ -32,7 +26,7 @@ struct fxn_info {
 };
 
 struct dup_handler {
-	struct blocks *b;
+	struct dup_blocks *b;
 	struct inode_with_dups *id;
 	int ref_inode_count;
 	int ref_count;
@@ -121,12 +115,12 @@ static int find_dentry(struct gfs2_inode *ip, struct gfs2_dirent *de,
 		       enum update_flags *update, uint16_t *count, void *priv)
 {
 	osi_list_t *tmp1, *tmp2;
-	struct blocks *b;
+	struct dup_blocks *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 blocks, list);
+		b = osi_list_entry(tmp1, struct dup_blocks, list);
 		osi_list_foreach(tmp2, &b->ref_inode_list) {
 			id = osi_list_entry(tmp2, struct inode_with_dups,
 					    list);
@@ -347,7 +341,7 @@ static int clear_eattr_extentry(struct gfs2_inode *ip, uint64_t *ea_data_ptr,
 }
 
 /* Finds all references to duplicate blocks in the metadata */
-int find_block_ref(struct gfs2_sbd *sbp, uint64_t inode, struct blocks *b)
+int find_block_ref(struct gfs2_sbd *sbp, uint64_t inode, struct dup_blocks *b)
 {
 	struct gfs2_inode *ip;
 	struct fxn_info myfi = {b->block_no, 0, 1};
@@ -402,7 +396,7 @@ int find_block_ref(struct gfs2_sbd *sbp, uint64_t inode, struct blocks *b)
 	return 0;
 }
 
-int handle_dup_blk(struct gfs2_sbd *sbp, struct blocks *b)
+int handle_dup_blk(struct gfs2_sbd *sbp, struct dup_blocks *b)
 {
 	osi_list_t *tmp;
 	struct inode_with_dups *id;
@@ -467,7 +461,7 @@ int handle_dup_blk(struct gfs2_sbd *sbp, struct blocks *b)
  * use in pass2 */
 int pass1b(struct gfs2_sbd *sbp)
 {
-	struct blocks *b;
+	struct dup_blocks *b;
 	uint64_t i;
 	struct gfs2_block_query q;
 	osi_list_t *tmp = NULL, *x;
@@ -507,7 +501,8 @@ int pass1b(struct gfs2_sbd *sbp)
 		   (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 blocks, list);
+				b = osi_list_entry(tmp, struct dup_blocks,
+						   list);
 				if(find_block_ref(sbp, i, b)) {
 					stack;
 					rc = FSCK_ERROR;
@@ -525,8 +520,8 @@ int pass1b(struct gfs2_sbd *sbp)
 	log_info("Handling duplicate blocks\n");
 out:
 	while (!osi_list_empty(&sbp->dup_blocks.list)) {
-		b = osi_list_entry(&sbp->dup_blocks.list.next, struct blocks,
-				   list);
+		b = osi_list_entry(sbp->dup_blocks.list.next,
+				   struct dup_blocks, list);
 		if (!skip_this_pass && !rc) /* no error & not asked to skip the rest */
 			handle_dup_blk(sbp, b);
 		osi_list_del(&b->list);
diff --git a/gfs2/libgfs2/block_list.c b/gfs2/libgfs2/block_list.c
index 4e51226..092d045 100644
--- a/gfs2/libgfs2/block_list.c
+++ b/gfs2/libgfs2/block_list.c
@@ -182,6 +182,19 @@ void gfs2_special_free(struct special_blocks *blist)
 	}
 }
 
+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;
@@ -196,6 +209,20 @@ struct special_blocks *blockfind(struct special_blocks *blist, uint64_t num)
 	return NULL;
 }
 
+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;
@@ -204,12 +231,29 @@ void gfs2_special_set(struct special_blocks *blocklist, uint64_t block)
 		return;
 	b = malloc(sizeof(struct special_blocks));
 	if (b) {
+		memset(b, 0, sizeof(*b));
 		b->block = block;
 		osi_list_add(&b->list, &blocklist->list);
 	}
 	return;
 }
 
+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_special_clear(struct special_blocks *blocklist, uint64_t block)
 {
 	struct special_blocks *b;
@@ -221,6 +265,17 @@ static void gfs2_special_clear(struct special_blocks *blocklist, uint64_t block)
 	}
 }
 
+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);
+	}
+}
+
 int gfs2_block_mark(struct gfs2_sbd *sdp, struct gfs2_block_list *il,
 		    uint64_t block, enum gfs2_mark_block mark)
 {
@@ -229,7 +284,7 @@ int gfs2_block_mark(struct gfs2_sbd *sdp, struct gfs2_block_list *il,
 	if(mark == gfs2_bad_block)
 		gfs2_special_set(&sdp->bad_blocks, block);
 	else if(mark == gfs2_dup_block)
-		gfs2_special_set(&sdp->dup_blocks, block);
+		gfs2_dup_set(&sdp->dup_blocks, block);
 	else if(mark == gfs2_eattr_block)
 		gfs2_special_set(&sdp->eattr_blocks, block);
 	else
@@ -245,7 +300,7 @@ int gfs2_block_clear(struct gfs2_sbd *sdp, struct gfs2_block_list *il,
 
 	switch (m) {
 	case gfs2_dup_block:
-		gfs2_special_clear(&sdp->dup_blocks, block);
+		gfs2_dup_clear(&sdp->dup_blocks, block);
 		break;
 	case gfs2_bad_block:
 		gfs2_special_clear(&sdp->bad_blocks, block);
@@ -285,7 +340,7 @@ int gfs2_block_check(struct gfs2_sbd *sdp, struct gfs2_block_list *il,
 		return err;
 	if (blockfind(&sdp->bad_blocks, block))
 		val->bad_block = 1;
-	if (blockfind(&sdp->dup_blocks, block))
+	if (dupfind(&sdp->dup_blocks, block))
 		val->dup_block = 1;
 	if (blockfind(&sdp->eattr_blocks, block))
 		val->eattr_block = 1;
@@ -300,7 +355,7 @@ void *gfs2_block_list_destroy(struct gfs2_sbd *sdp, struct gfs2_block_list *il)
 		il = NULL;
 	}
 	gfs2_special_free(&sdp->bad_blocks);
-	gfs2_special_free(&sdp->dup_blocks);
+	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 633aff3..5022f75 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -116,6 +116,12 @@ struct gfs2_buffer_head {
 	int b_changed;
 };
 
+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;
@@ -246,7 +252,7 @@ struct gfs2_sbd {
 	int metafs_fd;
 	char metafs_path[PATH_MAX]; /* where metafs is mounted */
 	struct special_blocks bad_blocks;
-	struct special_blocks dup_blocks;
+	struct dup_blocks dup_blocks;
 	struct special_blocks eattr_blocks;
 };
 


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2009-04-20 18:26 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-04-20 18:26 cluster: STABLE3 - Fix gfs2_fsck segfault Bob Peterson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).