public inbox for cluster-cvs@sourceware.org
help / color / mirror / Atom feed
* gfs2-utils: master - 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/gfs2-utils.git?p=gfs2-utils.git;a=commitdiff;h=22c397f3a8495b62e50c271dbcd4fb11c8342af0
Commit:        22c397f3a8495b62e50c271dbcd4fb11c8342af0
Parent:        33d84bd3b7c27e5c7ed09825ca16b2648e622673
Author:        Bob Peterson <rpeterso@redhat.com>
AuthorDate:    Mon Apr 20 13:14:39 2009 -0500
Committer:     Bob Peterson <rpeterso@redhat.com>
CommitterDate: Mon Apr 20 13:14:39 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 ba3f860..d1edb94 100644
--- a/gfs2/fsck/pass1b.c
+++ b/gfs2/fsck/pass1b.c
@@ -21,12 +21,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;
@@ -34,7 +28,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;
@@ -122,12 +116,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);
@@ -348,7 +342,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};
@@ -403,7 +397,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;
@@ -468,7 +462,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;
@@ -508,7 +502,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;
@@ -526,8 +521,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 gfs2-utils: master - 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).