[PATCH] Better RAS when btstack is overrun (2 of 2)

[email protected] Thu, 10 Jun 2004 12:41:53 -0500
Newsgroups gmane.comp.file-systems.jfs.patches
Message-ID <[email protected]>
# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/06/09 16:32:52-05:00 [email protected] 
#   JFS: Better RAS when btstack is overrun
#   
#   The current warning and/or trap when the btstack is overrun in
#   dtSearch or dtReadFirst are not very helpful.  Add code to detect
#   the stack overrun earlier, print something useful, and return
#   gracefully.
#   
#   I've found that dbFree being called with blkno == 0 can lead to this
#   error, so I put in a specific check for that.
#   
#   Signed-off-by: Dave Kleikamp <[email protected]>
# 
diff -Nru a/fs/jfs/jfs_btree.h b/fs/jfs/jfs_btree.h
--- a/fs/jfs/jfs_btree.h	2004-06-10 12:37:22 -05:00
+++ b/fs/jfs/jfs_btree.h	2004-06-10 12:37:22 -05:00
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) International Business Machines Corp., 2000-2001
+ *   Copyright (C) International Business Machines Corp., 2000-2004
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -108,13 +108,12 @@
  * record the path traversed during the search;
  * top frame record the leaf page/entry selected.
  */
-#define	MAXTREEHEIGHT		8
 struct btframe {	/* stack frame */
 	s64 bn;			/* 8: */
 	s16 index;		/* 2: */
-	s16 lastindex;		/* 2: */
-	struct metapage *mp;	/* 4: */
-};				/* (16) */
+	s16 lastindex;		/* 2: unused */
+	struct metapage *mp;	/* 4/8: */
+};				/* (16/24) */
 
 struct btstack {
 	struct btframe *top;
@@ -125,12 +124,15 @@
 #define BT_CLR(btstack)\
 	(btstack)->top = (btstack)->stack
 
+#define BT_STACK_FULL(btstack)\
+	( (btstack)->top == &((btstack)->stack[MAXTREEHEIGHT-1]))
+
 #define BT_PUSH(BTSTACK, BN, INDEX)\
 {\
+	assert(!BT_STACK_FULL(BTSTACK));\
 	(BTSTACK)->top->bn = BN;\
 	(BTSTACK)->top->index = INDEX;\
 	++(BTSTACK)->top;\
-	assert((BTSTACK)->top != &((BTSTACK)->stack[MAXTREEHEIGHT]));\
 }
 
 #define BT_POP(btstack)\
@@ -138,6 +140,16 @@
 
 #define BT_STACK(btstack)\
 	( (btstack)->top == (btstack)->stack ? NULL : (btstack)->top )
+
+static inline void BT_STACK_DUMP(struct btstack *btstack)
+{
+	int i;
+	printk("btstack dump:\n");
+	for (i = 0; i < MAXTREEHEIGHT; i++)
+		printk(KERN_ERR "bn = %Lx, index = %d\n",
+		       btstack->stack[i].bn,
+		       btstack->stack[i].index);
+}
 
 /* retrieve search results */
 #define BT_GETSEARCH(IP, LEAF, BN, MP, TYPE, P, INDEX, ROOT)\
diff -Nru a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
--- a/fs/jfs/jfs_dmap.c	2004-06-10 12:37:22 -05:00
+++ b/fs/jfs/jfs_dmap.c	2004-06-10 12:37:22 -05:00
@@ -1,5 +1,5 @@
 /*
- *   Copyright (C) International Business Machines Corp., 2000-2003
+ *   Copyright (C) International Business Machines Corp., 2000-2004
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -382,7 +382,7 @@
 	IREAD_LOCK(ipbmap);
 
 	/* block to be freed better be within the mapsize. */
-	if (blkno + nblocks > bmp->db_mapsize) {
+	if (unlikely((blkno == 0) || (blkno + nblocks > bmp->db_mapsize))) {
 		IREAD_UNLOCK(ipbmap);
 		printk(KERN_ERR "blkno = %Lx, nblocks = %Lx\n",
 		       (unsigned long long) blkno,
diff -Nru a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
--- a/fs/jfs/jfs_dtree.c	2004-06-10 12:37:22 -05:00
+++ b/fs/jfs/jfs_dtree.c	2004-06-10 12:37:22 -05:00
@@ -1,5 +1,5 @@
 /*
- *   Copyright (C) International Business Machines Corp., 2000-2003
+ *   Copyright (C) International Business Machines Corp., 2000-2004
  *
  *   This program is free software;  you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -766,11 +766,12 @@
 		 */
 	      getChild:
 		/* update max. number of pages to split */
-		if (btstack->nsplit >= 8) {
+		if (BT_STACK_FULL(btstack)) {
 			/* Something's corrupted, mark filesytem dirty so
 			 * chkdsk will fix it.
 			 */
 			jfs_error(sb, "stack overrun in dtSearch!");
+			BT_STACK_DUMP(btstack);
 			rc = -EIO;
 			goto out;
 		}
@@ -3346,6 +3347,12 @@
 		/*
 		 * descend down to leftmost child page
 		 */
+		if (BT_STACK_FULL(btstack)) {
+			DT_PUTPAGE(mp);
+			jfs_error(ip->i_sb, "dtReadFirst: btstack overrun");
+			BT_STACK_DUMP(btstack);
+			return -EIO;
+		}
 		/* push (bn, index) of the parent page/entry */
 		BT_PUSH(btstack, bn, 0);
 
diff -Nru a/fs/jfs/jfs_types.h b/fs/jfs/jfs_types.h
--- a/fs/jfs/jfs_types.h	2004-06-10 12:37:22 -05:00
+++ b/fs/jfs/jfs_types.h	2004-06-10 12:37:22 -05:00
@@ -113,11 +113,12 @@
 #define	addressPXD(pxd)\
 	( ((s64)((pxd)->addr1)) << 32 | __le32_to_cpu((pxd)->addr2))
 
+#define MAXTREEHEIGHT 8
 /* pxd list */
 struct pxdlist {
 	s16 maxnpxd;
 	s16 npxd;
-	pxd_t pxd[8];
+	pxd_t pxd[MAXTREEHEIGHT];
 };