[Ocfs2-tools-devel] [PATCH 1/3] fsck.ocfs2: Handle errors from ocfs2_bitmap_set/clear()

Joel Becker joel.becker at oracle.com
Fri Jun 19 22:08:20 PDT 2009


o2fsck expects to be able to treat ocfs2_bitmap_set() and
ocfs2_bitmap_clear() as void functions.  However, since o2fsck uses the
sparse-memory bitmaps a lot, they can (in theory) have allocation
failures.  A silent allocation failure looks like clear bits, which is
not a safe behavior.

So, let's wrap ocfs2_bitmap_set/clear() with o2fsck_bitmap_set/clear().
These are true void functions.  If they get an error from
ocfs2_bitmap_set/clear() they will print the caller, the error, and the
bit number.  Then they abort o2fsck.

Signed-off-by: Joel Becker <joel.becker at oracle.com>
---
 fsck.ocfs2/icount.c       |    4 ++--
 fsck.ocfs2/include/util.h |   15 +++++++++++++++
 fsck.ocfs2/journal.c      |    2 +-
 fsck.ocfs2/pass0.c        |   10 +++++-----
 fsck.ocfs2/pass1.c        |    4 ++--
 fsck.ocfs2/util.c         |   43 +++++++++++++++++++++++++++++++++++++++++--
 6 files changed, 66 insertions(+), 12 deletions(-)

diff --git a/fsck.ocfs2/icount.c b/fsck.ocfs2/icount.c
index 858063a..1fa7aab 100644
--- a/fsck.ocfs2/icount.c
+++ b/fsck.ocfs2/icount.c
@@ -95,9 +95,9 @@ errcode_t o2fsck_icount_set(o2fsck_icount *icount, uint64_t blkno,
 	errcode_t ret = 0;
 
 	if (count == 1)
-		ocfs2_bitmap_set(icount->ic_single_bm, blkno, NULL);
+		o2fsck_bitmap_set(icount->ic_single_bm, blkno, NULL);
 	else
-		ocfs2_bitmap_clear(icount->ic_single_bm, blkno, NULL);
+		o2fsck_bitmap_clear(icount->ic_single_bm, blkno, NULL);
 
 	in = icount_search(icount, blkno, NULL);
 	if (in) {
diff --git a/fsck.ocfs2/include/util.h b/fsck.ocfs2/include/util.h
index 77d36e4..c4e58ba 100644
--- a/fsck.ocfs2/include/util.h
+++ b/fsck.ocfs2/include/util.h
@@ -65,4 +65,19 @@ errcode_t handle_slots_system_file(ocfs2_filesys *fs,
 				   errcode_t (*func)(ocfs2_filesys *fs,
 						     struct ocfs2_dinode *di,
 						     int slot));
+
+/*
+ * Wrap the ocfs2 bitmap functions to abort when errors are found.  They're
+ * not supposed to fail, so we want to handle it.
+ */
+void __o2fsck_bitmap_set(ocfs2_bitmap *bitmap, uint64_t bitno, int *oldval,
+			 const char *where);
+void __o2fsck_bitmap_clear(ocfs2_bitmap *bitmap, uint64_t bitno, int *oldval,
+			   const char *where);
+
+/* These wrappers pass the caller into __o2fsck_bitmap_*() */
+#define o2fsck_bitmap_set(_map, _bit, _old)     			\
+	__o2fsck_bitmap_set((_map), (_bit), (_old), __FUNCTION__)
+#define o2fsck_bitmap_clear(_map, _bit, _old)				\
+	__o2fsck_bitmap_clear((_map), (_bit), (_old), __FUNCTION__);
 #endif /* __O2FSCK_UTIL_H__ */
diff --git a/fsck.ocfs2/journal.c b/fsck.ocfs2/journal.c
index 4ed7653..ee1ce60 100644
--- a/fsck.ocfs2/journal.c
+++ b/fsck.ocfs2/journal.c
@@ -247,7 +247,7 @@ static errcode_t lookup_journal_block(ocfs2_filesys *fs,
 	}
 
 	if (check_dup) {
-		ocfs2_bitmap_set(ji->ji_used_blocks, *blkno, &was_set);
+		o2fsck_bitmap_set(ji->ji_used_blocks, *blkno, &was_set);
 		if (was_set)  {
 			printf("Logical block %"PRIu64" in slot %d's journal "
 			       "maps to block %"PRIu64" which has already "
diff --git a/fsck.ocfs2/pass0.c b/fsck.ocfs2/pass0.c
index b2172ce..66e18c7 100644
--- a/fsck.ocfs2/pass0.c
+++ b/fsck.ocfs2/pass0.c
@@ -494,13 +494,13 @@ static errcode_t check_chain(o2fsck_state *ost,
 				int was_set;
 				ocfs2_bitmap_test(allowed, blkno, &was_set);
 				if (was_set) {
-					ocfs2_bitmap_clear(allowed, blkno,
-							   &was_set);
+					o2fsck_bitmap_clear(allowed, blkno,
+							    &was_set);
 					mark_group_used(ost, cs, bg1->bg_blkno,
 							allowed != NULL);
 				} else if (forbidden)
-					ocfs2_bitmap_set(forbidden, blkno,
-							 &was_set);
+					o2fsck_bitmap_set(forbidden, blkno,
+							  &was_set);
 			} else
 				mark_group_used(ost, cs, bg1->bg_blkno,
 						allowed != NULL);
@@ -906,7 +906,7 @@ static errcode_t verify_bitmap_descs(o2fsck_state *ost,
 	     i < cgs.cgs_cluster_groups; 
 	     i++, blkno = i * ocfs2_clusters_to_blocks(ost->ost_fs,
 						       cgs.cgs_cpg)) {
-		ocfs2_bitmap_set(allowed, blkno, NULL);
+		o2fsck_bitmap_set(allowed, blkno, NULL);
 	}
 
 	ret = verify_chain_alloc(ost, di, buf1, buf2, NULL, allowed, forbidden);
diff --git a/fsck.ocfs2/pass1.c b/fsck.ocfs2/pass1.c
index 15880bc..de09788 100644
--- a/fsck.ocfs2/pass1.c
+++ b/fsck.ocfs2/pass1.c
@@ -509,11 +509,11 @@ static void o2fsck_verify_inode_fields(ocfs2_filesys *fs,
 	}
 
 	if (S_ISDIR(di->i_mode)) {
-		ocfs2_bitmap_set(ost->ost_dir_inodes, blkno, NULL);
+		o2fsck_bitmap_set(ost->ost_dir_inodes, blkno, NULL);
 		o2fsck_add_dir_parent(&ost->ost_dir_parents, blkno, 0, 0,
 				      di->i_flags & OCFS2_ORPHANED_FL);
 	} else if (S_ISREG(di->i_mode)) {
-		ocfs2_bitmap_set(ost->ost_reg_inodes, blkno, NULL);
+		o2fsck_bitmap_set(ost->ost_reg_inodes, blkno, NULL);
 	} else if (S_ISLNK(di->i_mode)) {
 		/* we only make sure a link's i_size matches
 		 * the link names length in the file data later when
diff --git a/fsck.ocfs2/util.c b/fsck.ocfs2/util.c
index 0238709..b12e3e1 100644
--- a/fsck.ocfs2/util.c
+++ b/fsck.ocfs2/util.c
@@ -28,6 +28,9 @@
 #include <inttypes.h>
 #include <string.h>
 #include <assert.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <unistd.h>
 #include "ocfs2/ocfs2.h"
 
 #include "util.h"
@@ -57,7 +60,7 @@ void o2fsck_mark_cluster_allocated(o2fsck_state *ost, uint32_t cluster)
 {
 	int was_set;
 
-	ocfs2_bitmap_set(ost->ost_allocated_clusters, cluster, &was_set);
+	o2fsck_bitmap_set(ost->ost_allocated_clusters, cluster, &was_set);
 
 	if (was_set) /* XX can go away one all callers handle this */
 		com_err(__FUNCTION__, OCFS2_ET_INTERNAL_FAILURE,
@@ -75,7 +78,7 @@ void o2fsck_mark_cluster_unallocated(o2fsck_state *ost, uint32_t cluster)
 {
 	int was_set;
 
-	ocfs2_bitmap_clear(ost->ost_allocated_clusters, cluster, &was_set);
+	o2fsck_bitmap_clear(ost->ost_allocated_clusters, cluster, &was_set);
 }
 
 errcode_t o2fsck_type_from_dinode(o2fsck_state *ost, uint64_t ino,
@@ -275,3 +278,39 @@ void o2fsck_reset_blocks_cached(void)
 {
 	blocks_cached = 0;
 }
+
+void __o2fsck_bitmap_set(ocfs2_bitmap *bitmap, uint64_t bitno, int *oldval,
+			 const char *where)
+{
+	errcode_t ret;
+
+	ret = ocfs2_bitmap_set(bitmap, bitno, oldval);
+	if (ret) {
+		com_err(where, ret,
+			"while trying to set bit %"PRIu64", aborting\n",
+			bitno);
+		/*
+		 * We abort with SIGTERM so that the signal handler can
+		 * clean up the cluster stack.
+		 */
+		kill(getpid(), SIGTERM);
+	}
+}
+
+void __o2fsck_bitmap_clear(ocfs2_bitmap *bitmap, uint64_t bitno, int *oldval,
+			   const char *where)
+{
+	errcode_t ret;
+
+	ret = ocfs2_bitmap_clear(bitmap, bitno, oldval);
+	if (ret) {
+		com_err(where, ret,
+			"while trying to clear bit %"PRIu64", aborting\n",
+			bitno);
+		/*
+		 * We abort with SIGTERM so that the signal handler can
+		 * clean up the cluster stack.
+		 */
+		kill(getpid(), SIGTERM);
+	}
+}
-- 
1.6.3.1




More information about the Ocfs2-tools-devel mailing list