JFS: Avoid BUG() on a damaged file system
authorDave Kleikamp <shaggy@linux.vnet.ibm.com>
Tue, 9 Jan 2007 14:57:34 +0000 (08:57 -0600)
committerDave Kleikamp <shaggy@linux.vnet.ibm.com>
Tue, 9 Jan 2007 14:57:34 +0000 (08:57 -0600)
On Mon, 2006-12-18 at 19:51 +0100, Eric Sesterhenn wrote:
> hi,
>
> while playing around with fsfuzzer, i got the following oops with jfs:
>
> [  851.804875] BUG at fs/jfs/jfs_xtree.c:760
> assert(!BT_STACK_FULL(btstack))
> [  851.805179] ------------[ cut here ]------------
> [  851.805238] kernel BUG at fs/jfs/jfs_xtree.c:760!

JFS should mark the superblock dirty and return an error rather than
calling BUG().

Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
fs/jfs/jfs_xtree.c

index e98eb03e53105083b3fb33b0c35b11a3c5b3f8f3..acc97c46d8a4096125ce4e2355a12e779d7aa376 100644 (file)
@@ -757,6 +757,11 @@ static int xtSearch(struct inode *ip, s64 xoff,    s64 *nextp,
                        nsplit = 0;
 
                /* push (bn, index) of the parent page/entry */
+               if (BT_STACK_FULL(btstack)) {
+                       jfs_error(ip->i_sb, "stack overrun in xtSearch!");
+                       XT_PUTPAGE(mp);
+                       return -EIO;
+               }
                BT_PUSH(btstack, bn, index);
 
                /* get the child page block number */
@@ -3915,6 +3920,11 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag)
         */
       getChild:
        /* save current parent entry for the child page */
+       if (BT_STACK_FULL(&btstack)) {
+               jfs_error(ip->i_sb, "stack overrun in xtTruncate!");
+               XT_PUTPAGE(mp);
+               return -EIO;
+       }
        BT_PUSH(&btstack, bn, index);
 
        /* get child page */
@@ -4112,6 +4122,11 @@ s64 xtTruncate_pmap(tid_t tid, struct inode *ip, s64 committed_size)
         */
       getChild:
        /* save current parent entry for the child page */
+       if (BT_STACK_FULL(&btstack)) {
+               jfs_error(ip->i_sb, "stack overrun in xtTruncate_pmap!");
+               XT_PUTPAGE(mp);
+               return -EIO;
+       }
        BT_PUSH(&btstack, bn, index);
 
        /* get child page */