summaryrefslogtreecommitdiff
path: root/fs/jfs
diff options
context:
space:
mode:
authorDave Kleikamp <shaggy@austin.ibm.com>2004-06-09 06:32:52 -0500
committerDave Kleikamp <jfs.adm@hostme.bitkeeper.com>2004-06-09 06:32:52 -0500
commitfa2c79c3514bacb3dfd84591e326a91094f7fc13 (patch)
tree91dd690ccaf4f0e2255a5ed12c03bac2ecb72285 /fs/jfs
parent86f996c0bef08b809581a8266a8d2c4a99deb4cd (diff)
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 <shaggy@austin.ibm.com>
Diffstat (limited to 'fs/jfs')
-rw-r--r--fs/jfs/jfs_btree.h24
-rw-r--r--fs/jfs/jfs_dmap.c4
-rw-r--r--fs/jfs/jfs_dtree.c11
-rw-r--r--fs/jfs/jfs_types.h3
4 files changed, 31 insertions, 11 deletions
diff --git a/fs/jfs/jfs_btree.h b/fs/jfs/jfs_btree.h
index 53c0a6ea72d8..ba4fb09f5fa2 100644
--- a/fs/jfs/jfs_btree.h
+++ b/fs/jfs/jfs_btree.h
@@ -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 @@ struct btpage {
* 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 @@ struct btstack {
#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)\
@@ -139,6 +141,16 @@ struct btstack {
#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 --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
index 3e9e629f4c2f..1b55df36f5cc 100644
--- a/fs/jfs/jfs_dmap.c
+++ b/fs/jfs/jfs_dmap.c
@@ -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 @@ int dbFree(struct inode *ip, s64 blkno, s64 nblocks)
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 --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
index b125ca4f9ebe..3c3140dd758f 100644
--- a/fs/jfs/jfs_dtree.c
+++ b/fs/jfs/jfs_dtree.c
@@ -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 @@ int dtSearch(struct inode *ip, struct component_name * key, ino_t * data,
*/
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 @@ static int dtReadFirst(struct inode *ip, struct btstack * btstack)
/*
* 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 --git a/fs/jfs/jfs_types.h b/fs/jfs/jfs_types.h
index 87ecbab5d66f..3fefbf063a93 100644
--- a/fs/jfs/jfs_types.h
+++ b/fs/jfs/jfs_types.h
@@ -113,11 +113,12 @@ typedef struct {
#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];
};