Dave Kleikamp | 24 Oct 16:39 2003
Picon

[PATCH] Improved error handing (2 of 2)

# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.1154  -> 1.1155 
#	 fs/jfs/jfs_filsys.h	1.2     -> 1.3    
#	      fs/jfs/xattr.c	1.10    -> 1.11   
#	      fs/jfs/namei.c	1.17    -> 1.18   
#	 fs/jfs/jfs_txnmgr.c	1.28    -> 1.29   
#	   fs/jfs/jfs_dmap.c	1.9     -> 1.10   
#	   fs/jfs/jfs_imap.c	1.14    -> 1.15   
#	fs/jfs/jfs_superblock.h	1.2     -> 1.3    
#	Documentation/filesystems/jfs.txt	1.5     -> 1.6    
#	 fs/jfs/jfs_extent.c	1.9     -> 1.10   
#	fs/jfs/jfs_metapage.c	1.9     -> 1.10   
#	  fs/jfs/jfs_dtree.c	1.13    -> 1.14   
#	     fs/jfs/resize.c	1.9     -> 1.10   
#	  fs/jfs/jfs_xtree.c	1.8     -> 1.9    
#	      fs/jfs/super.c	1.21    -> 1.22   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/10/14	shaggy <at> shaggy.austin.ibm.com	1.1155
# JFS: Improved error handing
#                                                                                 
# This patch replaces many assert statements, which caused a BUG(), with
# improved code to mark the superblock dirty and then proceed as specified by
# the errors= mount flag (as ext2 and ext3 do).  JFS's default for the errors
# option is "remount-ro" in order to prevent addition data corruption when a
# problem is found.
#                                                                                 
# These asserts are usually triggered by on-disk data corruption.  By marking
# the superblock dirty, fsck will perform a complete check on the file system
# and correct the problems, rather than simply replaying the journal, inviting
# later trouble.
#                                                                                 
# Submitted by Karl Rister & Dave Kleikamp
# --------------------------------------------
#
diff -Nru a/Documentation/filesystems/jfs.txt b/Documentation/filesystems/jfs.txt
--- a/Documentation/filesystems/jfs.txt	Fri Oct 24 09:30:35 2003
+++ b/Documentation/filesystems/jfs.txt	Fri Oct 24 09:30:35 2003
 <at>  <at>  -32,6 +32,10  <at>  <at> 
 		option to remount a volume where the nointegrity option was
 		previously specified in order to restore normal behavior.

+errors=continue		Keep going on a filesystem error.
+errors=remount-ro	Default. Remount the filesystem read-only on an error.
+errors=panic		Panic and halt the machine if an error occurs.
+
 JFS TODO list:

 Plans for our near term development items
diff -Nru a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
--- a/fs/jfs/jfs_dmap.c	Fri Oct 24 09:30:35 2003
+++ b/fs/jfs/jfs_dmap.c	Fri Oct 24 09:30:35 2003
 <at>  <at>  -1,5 +1,5  <at>  <at> 
 /*
- *   Copyright (c) International Business Machines Corp., 2000-2002
+ *   Copyright (C) International Business Machines Corp., 2000-2003
  *
  *   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
 <at>  <at>  -18,6 +18,7  <at>  <at> 

 #include <linux/fs.h>
 #include "jfs_incore.h"
+#include "jfs_superblock.h"
 #include "jfs_dmap.h"
 #include "jfs_imap.h"
 #include "jfs_lock.h"
 <at>  <at>  -135,7 +136,6  <at>  <at> 
 static int dbMaxBud(u8 * cp);
 s64 dbMapFileSizeToMapSize(struct inode *ipbmap);
 int blkstol2(s64 nb);
-void fsDirty(void);

 int cntlz(u32 value);
 int cnttz(u32 word);
 <at>  <at>  -383,20 +383,13  <at>  <at> 

 	/* block to be freed better be within the mapsize. */
 	if (unlikely(blkno + nblocks > bmp->db_mapsize)) {
-		/*
-		 * Trying to catch a bug here
-		 */
-		printk(KERN_ERR
-		       "JFS: dbFree asked to free block larger than mapsize\n");
-		printk(KERN_ERR
-		       "blkno = 0x%Lx, nblocks = 0x%Lx, mapsize = 0x%Lx\n",
-		       blkno, nblocks, bmp->db_mapsize);
-		printk(KERN_ERR "ino = %ld, cflag = %lx\n", ip->i_ino,
-		       JFS_IP(ip)->cflag);
-		dump_stack();
-		/* Make sure fsck fixes things back up */
-		updateSuper(ip->i_sb, FM_DIRTY);
-		return -EIO;	/* Nobody checks the return code */
+		IREAD_UNLOCK(ipbmap);
+		printk(KERN_ERR "blkno = %Lx, nblocks = %Lx\n",
+		       (unsigned long long) blkno,
+		       (unsigned long long) nblocks);
+		jfs_error(ip->i_sb,
+			  "dbFree: block to be freed is outside the map");
+		return -EIO;
 	}

 	/*
 <at>  <at>  -480,7 +473,14  <at>  <at> 
 	int lsn, difft, diffp;

 	/* the blocks better be within the mapsize. */
-	assert(blkno + nblocks <= bmp->db_mapsize);
+	if (blkno + nblocks > bmp->db_mapsize) {
+		printk(KERN_ERR "blkno = %Lx, nblocks = %Lx\n",
+		       (unsigned long long) blkno,
+		       (unsigned long long) nblocks);
+		jfs_error(ipbmap->i_sb,
+			  "dbUpdatePMap: blocks are outside the map");
+		return -EIO;
+	}

 	/* compute delta of transaction lsn from log syncpt */
 	lsn = tblk->lsn;
 <at>  <at>  -773,7 +773,10  <at>  <at> 
 	mapSize = bmp->db_mapsize;

 	/* the hint should be within the map */
-	assert(hint < mapSize);
+	if (hint >= mapSize) {
+		jfs_error(ip->i_sb, "dbAlloc: the hint is outside the map");
+		return -EIO;
+	}

 	/* if the number of blocks to be allocated is greater than the
 	 * allocation group size, try to allocate anywhere.
 <at>  <at>  -1120,7 +1123,12  <at>  <at> 

 	/* better be within the file system */
 	bmp = sbi->bmap;
-	assert(lastblkno >= 0 && lastblkno < bmp->db_mapsize);
+	if (lastblkno < 0 || lastblkno >= bmp->db_mapsize) {
+		IREAD_UNLOCK(ipbmap);
+		jfs_error(ip->i_sb,
+			  "dbExtend: the block is outside the filesystem");
+		return -EIO;
+	}

 	/* we'll attempt to extend the current allocation in place by
 	 * allocating the additional blocks as the blocks immediately
 <at>  <at>  -1161,11 +1169,10  <at>  <at> 
 		DBALLOC(bmp->db_DBmap, bmp->db_mapsize, extblkno,
 			addnblocks);
 		write_metapage(mp);
-	} else {
+	} else
 		/* we were not successful */
 		release_metapage(mp);
-		assert(rc == -ENOSPC || rc == -EIO);
-	}
+

 	return (rc);
 }
 <at>  <at>  -1430,7 +1437,12  <at>  <at> 
 	/* allocation request should not be for more than the
 	 * allocation group size.
 	 */
-	assert(l2nb <= bmp->db_agl2size);
+	if (l2nb > bmp->db_agl2size) {
+		jfs_error(bmp->db_ipbmap->i_sb,
+			  "dbAllocAG: allocation request is larger than the "
+			  "allocation group size");
+		return -EIO;
+	}

 	/* determine the starting block number of the allocation
 	 * group.
 <at>  <at>  -1457,13 +1469,13  <at>  <at> 
 	if (bmp->db_agsize == BPERDMAP
 	    || bmp->db_agfree[agno] == bmp->db_agsize) {
 		rc = dbAllocCtl(bmp, nblocks, l2nb, blkno, results);
-		/* assert(!(rc == -ENOSPC && bmp->db_agfree[agno] == bmp->db_agsize)); */
 		if ((rc == -ENOSPC) &&
 		    (bmp->db_agfree[agno] == bmp->db_agsize)) {
-			jfs_err("dbAllocAG: removed assert, but still need to "
-				"debug here\nblkno = 0x%Lx, nblocks = 0x%Lx",
-				(unsigned long long) blkno,
-				(unsigned long long) nblocks);
+			printk(KERN_ERR "blkno = %Lx, blocks = %Lx\n",
+			       (unsigned long long) blkno,
+			       (unsigned long long) nblocks);
+			jfs_error(bmp->db_ipbmap->i_sb,
+				  "dbAllocAG: dbAllocCtl failed in free AG");
 		}
 		return (rc);
 	}
 <at>  <at>  -1512,7 +1524,11  <at>  <at> 
 					break;
 				}
 			}
-			assert(n < 4);
+			if (n == 4) {
+				jfs_error(bmp->db_ipbmap->i_sb,
+					  "dbAllocAG: failed descending stree");
+				return -EIO;
+			}
 		}

 		/* determine the block number within the file system
 <at>  <at>  -1547,7 +1563,12  <at>  <at> 
 			if ((rc =
 			     dbFindCtl(bmp, l2nb, bmp->db_aglevel - 1,
 				       &blkno))) {
-				assert(rc != -ENOSPC);
+				if (rc == -ENOSPC) {
+					jfs_error(bmp->db_ipbmap->i_sb,
+						  "dbAllocAG: control page "
+						  "inconsistent");
+					return -EIO;
+				}
 				return (rc);
 			}
 		}
 <at>  <at>  -1555,7 +1576,11  <at>  <at> 
 		/* allocate the blocks.
 		 */
 		rc = dbAllocCtl(bmp, nblocks, l2nb, blkno, results);
-		assert(rc != -ENOSPC);
+		if (rc == -ENOSPC) {
+			jfs_error(bmp->db_ipbmap->i_sb,
+				  "dbAllocAG: unable to allocate blocks");
+			rc = -EIO;
+		}
 		return (rc);
 	}

 <at>  <at>  -1611,7 +1636,11  <at>  <at> 
 	/* allocate the blocks.
 	 */
 	rc = dbAllocCtl(bmp, nblocks, l2nb, blkno, results);
-	assert(rc != -ENOSPC);
+	if (rc == -ENOSPC) {
+		jfs_error(bmp->db_ipbmap->i_sb,
+			  "dbAllocAny: unable to allocate blocks");
+		return -EIO;
+	}
 	return (rc);
 }

 <at>  <at>  -1682,7 +1711,11  <at>  <at> 
 		/* space found ?
 		 */
 		if (rc) {
-			assert(lev == level);
+			if (lev != level) {
+				jfs_error(bmp->db_ipbmap->i_sb,
+					  "dbFindCtl: dmap inconsistent");
+				return -EIO;
+			}
 			return -ENOSPC;
 		}

 <at>  <at>  -1801,7 +1834,13  <at>  <at> 

 		/* the dmap better be all free.
 		 */
-		assert(dp->tree.stree[ROOT] == L2BPERDMAP);
+		if (dp->tree.stree[ROOT] != L2BPERDMAP) {
+			release_metapage(mp);
+			jfs_error(bmp->db_ipbmap->i_sb,
+				  "dbAllocCtl: the dmap is not all free");
+			rc = -EIO;
+			goto backout;
+		}

 		/* determine how many blocks to allocate from this dmap.
 		 */
 <at>  <at>  -1844,8 +1883,8  <at>  <at> 
 			/* could not back out.  mark the file system
 			 * to indicate that we have leaked blocks.
 			 */
-			fsDirty();	/* !!! */
-			jfs_err("dbAllocCtl: I/O Error: Block Leakage.");
+			jfs_error(bmp->db_ipbmap->i_sb,
+				  "dbAllocCtl: I/O Error: Block Leakage.");
 			continue;
 		}
 		dp = (struct dmap *) mp->data;
 <at>  <at>  -1857,8 +1896,8  <at>  <at> 
 			 * to indicate that we have leaked blocks.
 			 */
 			release_metapage(mp);
-			fsDirty();	/* !!! */
-			jfs_err("dbAllocCtl: Block Leakage.");
+			jfs_error(bmp->db_ipbmap->i_sb,
+				  "dbAllocCtl: Block Leakage.");
 			continue;
 		}

 <at>  <at>  -2153,7 +2192,12  <at>  <at> 
 			 * the allocated words.
 			 */
 			for (; nwords > 0; nwords -= nw) {
-				assert(leaf[word] >= BUDMIN);
+			        if (leaf[word] < BUDMIN) {
+					jfs_error(bmp->db_ipbmap->i_sb,
+						  "dbAllocBits: leaf page "
+						  "corrupt");
+					break;
+				}

 				/* determine what the leaf value should be
 				 * updated to as the minimum of the l2 number
 <at>  <at>  -2505,7 +2549,11  <at>  <at> 
 			 * of the maximum free buddy system.
 			 */
 			assert(level == bmp->db_maxlevel);
-			assert(bmp->db_maxfreebud == oldroot);
+			if (bmp->db_maxfreebud != oldroot) {
+				jfs_error(bmp->db_ipbmap->i_sb,
+					  "dbAdjCtl: the maximum free buddy is "
+					  "not the old root");
+			}
 			bmp->db_maxfreebud = dcp->stree[ROOT];
 		}
 	}
 <at>  <at>  -3056,24 +3104,6  <at>  <at> 

 
 /*
- * NAME:	fsDirty()
- *
- * FUNCTION:    xxx
- *
- * PARAMETERS:
- *      ipmnt	- mount inode
- *
- * RETURN VALUES:
- *      none
- */
-void fsDirty(void)
-{
-	printk("fsDirty(): bye-bye\n");
-	assert(0);
-}
-
-
-/*
  * NAME:    	dbAllocBottomUp()
  *
  * FUNCTION:	alloc the specified block range from the working block
 <at>  <at>  -3359,7 +3389,10  <at>  <at> 
 	/* get L2 page */
 	p = BMAPBLKNO + nbperpage;	/* L2 page */
 	l2mp = read_metapage(ipbmap, p, PSIZE, 0);
-	assert(l2mp);
+	if (!l2mp) {
+		jfs_error(ipbmap->i_sb, "dbExtendFS: L2 page could not be read");
+		return -EIO;
+	}
 	l2dcp = (struct dmapctl *) l2mp->data;

 	/* compute start L1 */
 <at>  <at>  -3520,7 +3553,9  <at>  <at> 
 		}
 	}			/* for each L1 in a L2 */

-	assert(0);
+	jfs_error(ipbmap->i_sb,
+		  "dbExtendFS: function has not returned as expected");
+	return -EIO;

 	/*
 	 *      finalize bmap control page
 <at>  <at>  -3584,7 +3619,10  <at>  <at> 
 			if (bmp->db_agfree[bmp->db_agpref] >= avgfree)
 				break;
 		}
-		assert(bmp->db_agpref < bmp->db_numag);
+		if (bmp->db_agpref >= bmp->db_numag) {
+			jfs_error(ipbmap->i_sb,
+				  "cannot find ag with average freespace");
+		}
 	}

 	/*
 <at>  <at>  -3605,10 +3643,6  <at>  <at> 
 		n <<= 2;
 	}

-/*
-printk("bmap: agpref:%d aglevel:%d agheigth:%d agwidth:%d\n",
-	bmp->db_agpref, bmp->db_aglevel, bmp->db_agheigth, bmp->db_agwidth);
-*/
 }

 
 <at>  <at>  -3632,9 +3666,6  <at>  <at> 
 static int dbInitDmap(struct dmap * dp, s64 Blkno, int nblocks)
 {
 	int blkno, w, b, r, nw, nb, i;
-/*
-printk("sbh_dmap:  in dbInitDmap blkno:%Ld nblocks:%ld\n", Blkno, nblocks); 
-*/

 	/* starting block number within the dmap */
 	blkno = Blkno & (BPERDMAP - 1);
 <at>  <at>  -3694,10 +3725,6  <at>  <at> 
 	 * mark bits following the range to be freed (non-existing 
 	 * blocks) as allocated (ONES)
 	 */
-/*
-printk("sbh_dmap:  in dbInitDmap, preparing to mark unbacked, blkno:%ld nblocks:%ld\n",
-		blkno, nblocks); 
-*/

 	if (blkno == BPERDMAP)
 		goto initTree;
 <at>  <at>  -3707,9 +3734,6  <at>  <at> 

 	/* does nblocks fall on a 32-bit boundary ? */
 	b = blkno & (DBWORD - 1);
-/*
-printk("sbh_dmap:  in dbInitDmap, b:%ld w:%ld mask: %lx\n", b, w, (ONES>>b)); 
-*/
 	if (b) {
 		/* mark a partial word allocated */
 		dp->wmap[w] = dp->pmap[w] = cpu_to_le32(ONES >> b);
 <at>  <at>  -4006,7 +4030,7  <at>  <at> 

 	dbmap = (u32 *) xmalloc(npages * 4096, L2PSIZE, kernel_heap);
 	if (dbmap == NULL)
-		assert(0);
+		BUG();	/* Not robust since this is only unused debug code */

 	for (n = 0, d = dbmap; n < npages; n++, d += 1024)
 		bzero(d, 4096);
 <at>  <at>  -4020,7 +4044,9  <at>  <at> 
 				   db_l2nbperpage);
 		mp = read_metapage(ipbmap, lblkno, PSIZE, 0);
 		if (mp == NULL) {
-			assert(0);
+			jfs_error(ipbmap->i_sb,
+				  "DBinitmap: could not read disk map page");
+			continue;
 		}
 		dp = (struct dmap *) mp->data;

diff -Nru a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
--- a/fs/jfs/jfs_dtree.c	Fri Oct 24 09:30:35 2003
+++ b/fs/jfs/jfs_dtree.c	Fri Oct 24 09:30:35 2003
 <at>  <at>  -1,5 +1,5  <at>  <at> 
 /*
- *   Copyright (c) International Business Machines Corp., 2000-2002
+ *   Copyright (C) International Business Machines Corp., 2000-2003
  *
  *   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
 <at>  <at>  -130,9 +130,8  <at>  <at> 
 		if (((P)->header.nextindex > (((BN)==0)?DTROOTMAXSLOT:(P)->header.maxslot)) ||\
 		    ((BN) && ((P)->header.maxslot > DTPAGEMAXSLOT)))\
 		{\
-			jfs_err("DT_GETPAGE: dtree page corrupt");\
 			BT_PUTPAGE(MP);\
-			updateSuper((IP)->i_sb, FM_DIRTY);\
+			jfs_error((IP)->i_sb, "DT_GETPAGE: dtree page corrupt");\
 			MP = NULL;\
 			RC = -EIO;\
 		}\
 <at>  <at>  -768,8 +767,7  <at>  <at> 
 			/* Something's corrupted, mark filesytem dirty so
 			 * chkdsk will fix it.
 			 */
-			jfs_err("stack overrun in dtSearch!");
-			updateSuper(sb, FM_DIRTY);
+			jfs_error(sb, "stack overrun in dtSearch!");
 			rc = -EIO;
 			goto out;
 		}
 <at>  <at>  -3204,11 +3202,12  <at>  <at> 
 				d_namleft -= len;
 				/* Sanity Check */
 				if (d_namleft == 0) {
-					jfs_err("JFS:Dtree error: ino = "
-						"%ld, bn=%Ld, index = %d",
-						(long)ip->i_ino,(long long)bn,
-						i);
-					updateSuper(ip->i_sb, FM_DIRTY);
+					jfs_error(ip->i_sb,
+						  "JFS:Dtree error: ino = "
+						  "%ld, bn=%Ld, index = %d",
+						  (long)ip->i_ino,
+						  (long long)bn,
+						  i);
 					goto skip_one;
 				}
 				len = min(d_namleft, DTSLOTDATALEN);
diff -Nru a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c
--- a/fs/jfs/jfs_extent.c	Fri Oct 24 09:30:35 2003
+++ b/fs/jfs/jfs_extent.c	Fri Oct 24 09:30:35 2003
 <at>  <at>  -1,5 +1,5  <at>  <at> 
 /*
- *   Copyright (c) International Business Machines Corp., 2000-2002
+ *   Copyright (C) International Business Machines Corp., 2000-2003
  *
  *   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
 <at>  <at>  -18,6 +18,7  <at>  <at> 

 #include <linux/fs.h>
 #include "jfs_incore.h"
+#include "jfs_superblock.h"
 #include "jfs_dmap.h"
 #include "jfs_extent.h"
 #include "jfs_debug.h"
 <at>  <at>  -404,8 +405,10  <at>  <at> 
 	 */
 	xp->flag &= XAD_NOTRECORDED;

-	assert(xadl.nxad == 1);
-	assert(lengthXAD(xp) == nbperpage);
+        if(xadl.nxad != 1 || lengthXAD(xp) != nbperpage) {          
+		jfs_error(ip->i_sb, "extHint: corrupt xtree");
+		return -EIO;
+        }

 	return (0);
 }
diff -Nru a/fs/jfs/jfs_filsys.h b/fs/jfs/jfs_filsys.h
--- a/fs/jfs/jfs_filsys.h	Fri Oct 24 09:30:35 2003
+++ b/fs/jfs/jfs_filsys.h	Fri Oct 24 09:30:35 2003
 <at>  <at>  -1,5 +1,5  <at>  <at> 
 /*
- *   Copyright (c) International Business Machines Corp., 2000-2003
+ *   Copyright (C) International Business Machines Corp., 2000-2003
  *
  *   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
 <at>  <at>  -31,6 +31,11  <at>  <at> 
  */
 /* mount time flag to disable journaling to disk */
 #define JFS_NOINTEGRITY 0x00000010
+
+/* mount time flags for error handling */
+#define JFS_ERR_REMOUNT_RO 0x00000002   /* remount read-only */
+#define JFS_ERR_CONTINUE   0x00000004   /* continue */
+#define JFS_ERR_PANIC      0x00000008   /* panic */

 /* platform option (conditional compilation) */
 #define JFS_AIX		0x80000000	/* AIX support */
diff -Nru a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
--- a/fs/jfs/jfs_imap.c	Fri Oct 24 09:30:35 2003
+++ b/fs/jfs/jfs_imap.c	Fri Oct 24 09:30:35 2003
 <at>  <at>  -1,5 +1,5  <at>  <at> 
 /*
- *   Copyright (c) International Business Machines Corp., 2000-2002
+ *   Copyright (C) International Business Machines Corp., 2000-2003
  *
  *   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
 <at>  <at>  -407,8 +407,7  <at>  <at> 
 	dp += rel_inode;

 	if (ip->i_ino != le32_to_cpu(dp->di_number)) {
-		jfs_err("diRead: i_ino != di_number");
-		updateSuper(ip->i_sb, FM_DIRTY);
+		jfs_error(ip->i_sb, "diRead: i_ino != di_number");
 		rc = -EIO;
 	} else if (le32_to_cpu(dp->di_nlink) == 0)
 		rc = -ESTALE;
 <at>  <at>  -645,9 +644,12  <at>  <at> 

 	ino = ip->i_ino & (INOSPERIAG - 1);

-	assert(lengthPXD(&(jfs_ip->ixpxd)) ==
-	       JFS_IP(ipimap)->i_imap->im_nbperiext);
-	assert(addressPXD(&(jfs_ip->ixpxd)));
+	if (!addressPXD(&(jfs_ip->ixpxd)) ||
+	    (lengthPXD(&(jfs_ip->ixpxd)) !=
+	     JFS_IP(ipimap)->i_imap->im_nbperiext)) {
+		jfs_error(ip->i_sb, "diWrite: ixpxd invalid");
+		return -EIO;
+	}

 	/*
 	 * read the page of disk inode containing the specified inode:
 <at>  <at>  -922,12 +924,11  <at>  <at> 
 	/* make sure that the iag is contained within 
 	 * the map.
 	 */
-	//assert(iagno < imap->im_nextiag);
 	if (iagno >= imap->im_nextiag) {
-		jfs_err("diFree: inum = %d, iagno = %d, nextiag = %d",
-			(uint) inum, iagno, imap->im_nextiag);
 		dump_mem("imap", imap, 32);
-		updateSuper(ip->i_sb, FM_DIRTY);
+		jfs_error(ip->i_sb,
+			  "diFree: inum = %d, iagno = %d, nextiag = %d",
+			  (uint) inum, iagno, imap->im_nextiag);
 		return -EIO;
 	}

 <at>  <at>  -961,22 +962,28  <at>  <at> 
 	bitno = ino & (INOSPEREXT - 1);
 	mask = HIGHORDER >> bitno;

-	assert(le32_to_cpu(iagp->wmap[extno]) & mask);
-#ifdef _STILL_TO_PORT
-	assert((le32_to_cpu(iagp->pmap[extno]) & mask) == 0);
-#endif				/*  _STILL_TO_PORT */
-	assert(addressPXD(&iagp->inoext[extno]));
+	if (!(le32_to_cpu(iagp->wmap[extno]) & mask)) {
+		jfs_error(ip->i_sb,
+			  "diFree: wmap shows inode already free");
+	}
+
+	if (!addressPXD(&iagp->inoext[extno])) {
+		release_metapage(mp);
+		IREAD_UNLOCK(ipimap);
+		AG_UNLOCK(imap, agno);
+		jfs_error(ip->i_sb, "diFree: invalid inoext");
+		return -EIO;
+	}

 	/* compute the bitmap for the extent reflecting the freed inode.
 	 */
 	bitmap = le32_to_cpu(iagp->wmap[extno]) & ~mask;

 	if (imap->im_agctl[agno].numfree > imap->im_agctl[agno].numinos) {
-		jfs_err("diFree: numfree > numinos");
 		release_metapage(mp);
 		IREAD_UNLOCK(ipimap);
 		AG_UNLOCK(imap, agno);
-		updateSuper(ip->i_sb, FM_DIRTY);
+		jfs_error(ip->i_sb, "diFree: numfree > numinos");
 		return -EIO;
 	}
 	/*
 <at>  <at>  -1140,7 +1147,6  <at>  <at> 
 				if ((rc =
 				     diIAGRead(imap, inofreefwd, &cmp)))
 					goto error_out;
-				assert(cmp != NULL);
 				ciagp = (struct iag *) cmp->data;
 			}
 			assert(ciagp != NULL);
 <at>  <at>  -1155,7 +1161,6  <at>  <at> 
 				if ((rc =
 				     diIAGRead(imap, inofreeback, &dmp)))
 					goto error_out;
-				assert(dmp != NULL);
 				diagp = (struct iag *) dmp->data;
 			}
 			assert(diagp != NULL);
 <at>  <at>  -1228,7 +1233,9  <at>  <at> 
 	 * the permanent map should have been updated already 
 	 * for the inode being freed.
 	 */
-	assert(iagp->pmap[extno] == 0);
+	if (iagp->pmap[extno] != 0) {
+		jfs_error(ip->i_sb, "diFree: the pmap does not show inode free");
+	}
 	iagp->wmap[extno] = 0;
 	DBG_DIFREE(imap, inum);
 	PXDlength(&iagp->inoext[extno], 0);
 <at>  <at>  -1308,7 +1315,7  <at>  <at> 
 	iplist[1] = (struct inode *) (size_t)iagno;
 	iplist[2] = (struct inode *) (size_t)extno;

-	rc = txCommit(tid, 1, &iplist[0], COMMIT_FORCE);	// D233382
+	rc = txCommit(tid, 1, &iplist[0], COMMIT_FORCE);

 	txEnd(tid);

 <at>  <at>  -1438,6 +1445,7  <at>  <at> 
 	iagno = INOTOIAG(inum);
 	if ((rc = diIAGRead(imap, iagno, &mp))) {
 		IREAD_UNLOCK(ipimap);
+		AG_UNLOCK(imap, agno);
 		return (rc);
 	}
 	iagp = (struct iag *) mp->data;
 <at>  <at>  -1540,10 +1548,16  <at>  <at> 
 				 */
 				rem = diFindFree(inosmap, 0);
 				extno = (sword << L2EXTSPERSUM) + rem;
-				rem =
-				    diFindFree(le32_to_cpu
-					       (iagp->wmap[extno]), 0);
-				assert(rem < INOSPEREXT);
+				rem = diFindFree(le32_to_cpu(iagp->wmap[extno]),
+						 0);
+				if (rem >= INOSPEREXT) {
+					IREAD_UNLOCK(ipimap);
+					AG_UNLOCK(imap, agno);
+					jfs_error(ip->i_sb,
+						  "diAlloc: can't find free bit "
+						  "in wmap");
+					return EIO;
+				}

 				/* determine the inode number within the
 				 * iag and allocate the inode from the
 <at>  <at>  -1552,9 +1566,9  <at>  <at> 
 				ino = (extno << L2INOSPEREXT) + rem;
 				rc = diAllocBit(imap, iagp, ino);
 				IREAD_UNLOCK(ipimap);
-				if (rc) {
+				if (rc)
 					assert(rc == -EIO);
-				} else {
+				else {
 					/* set the results of the allocation
 					 * and write the iag.
 					 */
 <at>  <at>  -1682,8 +1696,7  <at>  <at> 
 	numinos = imap->im_agctl[agno].numinos;

 	if (numfree > numinos) {
-		jfs_err("diAllocAG: numfree > numinos");
-		updateSuper(ip->i_sb, FM_DIRTY);
+		jfs_error(ip->i_sb, "diAllocAG: numfree > numinos");
 		return -EIO;
 	}

 <at>  <at>  -1831,12 +1844,10  <at>  <at> 
 	/* better be free inodes in this iag if it is on the
 	 * list.
 	 */
-	//assert(iagp->nfreeinos);
 	if (!iagp->nfreeinos) {
-		jfs_err("diAllocIno: nfreeinos = 0, but iag on freelist");
-		jfs_err("  agno = %d, iagno = %d", agno, iagno);
-		dump_mem("iag", iagp, 64);
-		updateSuper(ip->i_sb, FM_DIRTY);
+		IREAD_UNLOCK(imap->im_ipimap);
+		jfs_error(ip->i_sb,
+			  "diAllocIno: nfreeinos = 0, but iag on freelist");
 		return -EIO;
 	}

 <at>  <at>  -1844,7 +1855,12  <at>  <at> 
 	 * with free inodes.
 	 */
 	for (sword = 0;; sword++) {
-		assert(sword < SMAPSZ);
+		if (sword >= SMAPSZ) {
+			IREAD_UNLOCK(imap->im_ipimap);
+			jfs_error(ip->i_sb,
+				  "diAllocIno: free inode not found in summary map");
+			return -EIO;
+		}

 		if (~iagp->inosmap[sword])
 			break;
 <at>  <at>  -1854,13 +1870,21  <at>  <at> 
 	 * the extent number.
 	 */
 	rem = diFindFree(le32_to_cpu(iagp->inosmap[sword]), 0);
-	assert(rem < EXTSPERSUM);
+	if (rem >= EXTSPERSUM) {
+		IREAD_UNLOCK(imap->im_ipimap);
+		jfs_error(ip->i_sb, "diAllocIno: no free extent found");
+		return -EIO;
+	}
 	extno = (sword << L2EXTSPERSUM) + rem;

 	/* find the first free inode in the extent.
 	 */
 	rem = diFindFree(le32_to_cpu(iagp->wmap[extno]), 0);
-	assert(rem < INOSPEREXT);
+	if (rem >= INOSPEREXT) {
+		IREAD_UNLOCK(imap->im_ipimap);
+		jfs_error(ip->i_sb, "diAllocIno: free inode not found");
+		return -EIO;
+	}

 	/* compute the inode number within the iag. 
 	 */
 <at>  <at>  -1943,7 +1967,9  <at>  <at> 
 		 */
 		IREAD_LOCK(imap->im_ipimap);
 		if ((rc = diIAGRead(imap, iagno, &mp))) {
-			assert(0);
+			IREAD_UNLOCK(imap->im_ipimap);
+			jfs_error(ip->i_sb, "diAllocExt: error reading iag");
+			return rc;
 		}
 		iagp = (struct iag *) mp->data;
 	}
 <at>  <at>  -1951,7 +1977,13  <at>  <at> 
 	/* using the free extent summary map, find a free extent.
 	 */
 	for (sword = 0;; sword++) {
-		assert(sword < SMAPSZ);
+		if (sword >= SMAPSZ) {
+			release_metapage(mp);
+			IREAD_UNLOCK(imap->im_ipimap);
+			jfs_error(ip->i_sb,
+				  "diAllocExt: free ext summary map not found");
+			return -EIO;
+		}
 		if (~iagp->extsmap[sword])
 			break;
 	}
 <at>  <at>  -1959,7 +1991,12  <at>  <at> 
 	/* determine the extent number of the free extent.
 	 */
 	rem = diFindFree(le32_to_cpu(iagp->extsmap[sword]), 0);
-	assert(rem < EXTSPERSUM);
+	if (rem >= EXTSPERSUM) {
+		release_metapage(mp);
+		IREAD_UNLOCK(imap->im_ipimap);
+		jfs_error(ip->i_sb, "diAllocExt: free extent not found");
+		return -EIO;
+	}
 	extno = (sword << L2EXTSPERSUM) + rem;

 	/* initialize the new extent.
 <at>  <at>  -2070,9 +2107,18  <at>  <at> 

 	/* the inode should be free and backed.
 	 */
-	assert((le32_to_cpu(iagp->pmap[extno]) & mask) == 0);
-	assert((le32_to_cpu(iagp->wmap[extno]) & mask) == 0);
-	assert(addressPXD(&iagp->inoext[extno]) != 0);
+	if (((le32_to_cpu(iagp->pmap[extno]) & mask) != 0) ||
+	    ((le32_to_cpu(iagp->wmap[extno]) & mask) != 0) ||
+	    (addressPXD(&iagp->inoext[extno]) == 0)) {
+		if (amp)
+			release_metapage(amp);
+		if (bmp)
+			release_metapage(bmp);
+
+		jfs_error(imap->im_ipimap->i_sb,
+			  "diAllocBit: iag inconsistent");
+		return -EIO;
+	}

 	/* mark the inode as allocated in the working map.
 	 */
 <at>  <at>  -2176,7 +2222,10  <at>  <at> 

 	/* better have free extents.
 	 */
-	assert(iagp->nfreeexts);
+	if (!iagp->nfreeexts) {
+		jfs_error(imap->im_ipimap->i_sb, "diNewExt: no free extents");
+		return -EIO;
+	}

 	/* get the inode map inode.
 	 */
 <at>  <at>  -2244,7 +2293,12  <at>  <at> 
 					goto error_out;
 				ciagp = (struct iag *) cmp->data;
 			}
-			assert(ciagp != NULL);
+			if (ciagp == NULL) {
+				jfs_error(imap->im_ipimap->i_sb,
+					  "diNewExt: ciagp == NULL");
+				rc = -EIO;
+				goto error_out;
+			}
 		}
 	}

 <at>  <at>  -2478,7 +2532,14  <at>  <at> 
 		/* acquire inode map lock */
 		IWRITE_LOCK(ipimap);

-		assert(ipimap->i_size >> L2PSIZE == imap->im_nextiag + 1);
+		if (ipimap->i_size >> L2PSIZE != imap->im_nextiag + 1) {
+			IWRITE_UNLOCK(ipimap);
+			IAGFREE_UNLOCK(imap);
+			jfs_error(imap->im_ipimap->i_sb,
+				  "diNewIAG: ipimap->i_size is wrong");
+			return -EIO;
+		}
+

 		/* get the next avaliable iag number */
 		iagno = imap->im_nextiag;
 <at>  <at>  -2511,7 +2572,6  <at>  <at> 

 		/* assign a buffer for the page */
 		mp = get_metapage(ipimap, xaddr, PSIZE, 1);
-		//bp = bmAssign(ipimap, blkno, xaddr, PSIZE, bmREAD_PAGE);
 		if (!mp) {
 			/* Free the blocks allocated for the iag since it was
 			 * not successfully added to the inode map
 <at>  <at>  -2738,7 +2798,11  <at>  <at> 
 	/* get the iag number containing the inode */
 	iagno = INOTOIAG(inum);
 	/* make sure that the iag is contained within the map */
-	assert(iagno < imap->im_nextiag);
+	if (iagno >= imap->im_nextiag) {
+		jfs_error(ipimap->i_sb,
+			  "diUpdatePMap: the iag is outside the map");
+		return -EIO;
+	}
 	/* read the iag */
 	IREAD_LOCK(ipimap);
 	rc = diIAGRead(imap, iagno, &mp);
 <at>  <at>  -2763,14 +2827,14  <at>  <at> 
 		 * of last reference release;
 		 */
 		if (!(le32_to_cpu(iagp->wmap[extno]) & mask)) {
-			jfs_err("diUpdatePMap: inode %ld not marked as "
-				"allocated in wmap!", inum);
-			updateSuper(ipimap->i_sb, FM_DIRTY);
+			jfs_error(ipimap->i_sb, 
+				  "diUpdatePMap: inode %ld not marked as "
+				  "allocated in wmap!", inum);
 		}
 		if (!(le32_to_cpu(iagp->pmap[extno]) & mask)) {
-			jfs_err("diUpdatePMap: inode %ld not marked as "
-				"allocated in pmap!", inum);
-			updateSuper(ipimap->i_sb, FM_DIRTY);
+			jfs_error(ipimap->i_sb,
+				  "diUpdatePMap: inode %ld not marked as "
+				  "allocated in pmap!", inum);
 		}
 		/* update the bitmap for the extent of the freed inode */
 		iagp->pmap[extno] &= cpu_to_le32(~mask);
 <at>  <at>  -2782,8 +2846,18  <at>  <at> 
 		/* The inode should be already allocated in the working map
 		 * and should be free in persistent map;
 		 */
-		assert(le32_to_cpu(iagp->wmap[extno]) & mask);
-		assert((le32_to_cpu(iagp->pmap[extno]) & mask) == 0);
+		if (!(le32_to_cpu(iagp->wmap[extno]) & mask)) {
+			jfs_error(ipimap->i_sb,
+				  "diUpdatePMap: the inode is not allocated in "
+				  "the working map");
+			return -EIO;
+		}
+		if ((le32_to_cpu(iagp->pmap[extno]) & mask) != 0) {
+			jfs_error(ipimap->i_sb,
+				  "diUpdatePMap: the inode is not free in the "
+				  "persistent map");
+			return -EIO;
+		}
 		/* update the bitmap for the extent of the allocated inode */
 		iagp->pmap[extno] |= cpu_to_le32(mask);
 	}
 <at>  <at>  -2822,7 +2896,6  <at>  <at> 
 		mp->clsn = tblk->clsn;
 		LOGSYNC_UNLOCK(log);
 	}
-//      bmLazyWrite(mp, log->flag & JFS_COMMIT);
 	write_metapage(mp);
 	return (0);
 }
 <at>  <at>  -2877,7 +2950,12  <at>  <at> 
 			continue;
 		}
 		iagp = (struct iag *) bp->data;
-		assert(le32_to_cpu(iagp->iagnum) == i);
+		if (le32_to_cpu(iagp->iagnum) != i) {
+			release_metapage(bp);
+			jfs_error(ipimap->i_sb,
+				  "diExtendFs: unexpected value of iagnum");
+			return -EIO;
+		}

 		/* leave free iag in the free iag list */
 		if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG)) {  
 <at>  <at>  -2889,9 +2967,6  <at>  <at> 
 		agstart = le64_to_cpu(iagp->agstart);
 		/* iagp->agstart = agstart & ~(mp->db_agsize - 1); */
 		n = agstart >> mp->db_agl2size;
-/*
-printf("diExtendFS: iag:%d agstart:%Ld agno:%d\n", i, agstart, n);
-*/

 		/* compute backed inodes */
 		numinos = (EXTSPERIAG - le32_to_cpu(iagp->nfreeexts))
 <at>  <at>  -2952,8 +3027,12  <at>  <at> 
 		write_metapage(bp);
 	}

-	ASSERT(xnuminos == atomic_read(&imap->im_numinos) &&
-	       xnumfree == atomic_read(&imap->im_numfree));
+	if (xnuminos != atomic_read(&imap->im_numinos) ||
+	    xnumfree != atomic_read(&imap->im_numfree)) {
+		jfs_error(ipimap->i_sb,
+			  "diExtendFs: numinos or numfree incorrect");
+		return -EIO;
+	}

 	return rcx;
 }
diff -Nru a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
--- a/fs/jfs/jfs_metapage.c	Fri Oct 24 09:30:35 2003
+++ b/fs/jfs/jfs_metapage.c	Fri Oct 24 09:30:35 2003
 <at>  <at>  -1,6 +1,6  <at>  <at> 
 /*
- *   Copyright (c) International Business Machines Corp., 2000-2002
- *   Portions Copyright (c) Christoph Hellwig, 2001-2002
+ *   Copyright (C) International Business Machines Corp., 2000-2003
+ *   Portions Copyright (C) Christoph Hellwig, 2001-2002
  *
  *   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
 <at>  <at>  -20,6 +20,7  <at>  <at> 
 #include <linux/fs.h>
 #include <linux/init.h>
 #include "jfs_incore.h"
+#include "jfs_superblock.h"
 #include "jfs_filsys.h"
 #include "jfs_metapage.h"
 #include "jfs_txnmgr.h"
 <at>  <at>  -291,14 +292,23  <at>  <at> 
 	if (mp) {
 	      page_found:
 		if (test_bit(META_discard, &mp->flag)) {
-			assert(new);	/* It's okay to reuse a discarded
-					 * if we expect it to be empty
-					 */
+			if (!new) {
+				spin_unlock(&meta_lock);
+				jfs_error(inode->i_sb,
+					  "__get_metapage: using a "
+					  "discarded metapage");
+				return NULL;
+			}
 			clear_bit(META_discard, &mp->flag);
 		}
 		mp->count++;
 		jfs_info("__get_metapage: found 0x%p, in hash", mp);
-		assert(mp->logical_size == size);
+		if (mp->logical_size != size) {
+			spin_unlock(&meta_lock);
+			jfs_error(inode->i_sb,
+				  "__get_metapage: mp->logical_size != size");
+			return NULL;
+		}
 		lock_metapage(mp);
 		spin_unlock(&meta_lock);
 	} else {
diff -Nru a/fs/jfs/jfs_superblock.h b/fs/jfs/jfs_superblock.h
--- a/fs/jfs/jfs_superblock.h	Fri Oct 24 09:30:35 2003
+++ b/fs/jfs/jfs_superblock.h	Fri Oct 24 09:30:35 2003
 <at>  <at>  -1,5 +1,5  <at>  <at> 
 /*
- *   Copyright (c) International Business Machines Corp., 2000-2002
+ *   Copyright (C) International Business Machines Corp., 2000-2003
  *
  *   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
 <at>  <at>  -108,5 +108,6  <at>  <at> 

 extern int readSuper(struct super_block *, struct buffer_head **);
 extern int updateSuper(struct super_block *, uint);
+extern void jfs_error(struct super_block *, const char *, ...);

 #endif /*_H_JFS_SUPERBLOCK */
diff -Nru a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
--- a/fs/jfs/jfs_txnmgr.c	Fri Oct 24 09:30:35 2003
+++ b/fs/jfs/jfs_txnmgr.c	Fri Oct 24 09:30:35 2003
 <at>  <at>  -1,6 +1,6  <at>  <at> 
 /*
- *   Copyright (c) International Business Machines Corp., 2000-2003
- *   Portions Copyright (c) Christoph Hellwig, 2001-2002
+ *   Copyright (C) International Business Machines Corp., 2000-2003
+ *   Portions Copyright (C) Christoph Hellwig, 2001-2002
  *
  *   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
 <at>  <at>  -1422,7 +1422,6  <at>  <at> 
 		 * page is not itself logged, to prevent pageout of the map
 		 * page before the log;
 		 */
-		assert(tlck->type & tlckFREE);

 		/* log LOG_NOREDOINOEXT of the freed inode extent for
 		 * logredo() to start NoRedoPage filters, and to update
 <at>  <at>  -2635,7 +2634,7  <at>  <at> 
 	 * mark filesystem dirty
 	 */
 	if (dirty)
-		updateSuper(tblk->sb, FM_DIRTY);
+		jfs_error(tblk->sb, "txAbort");

 	return;
 }
 <at>  <at>  -2694,7 +2693,7  <at>  <at> 
 	/*
 	 * mark filesystem dirty
 	 */
-	updateSuper(cd->sb, FM_DIRTY);
+	jfs_error(cd->sb, "txAbortCommit");
 }

 
diff -Nru a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c
--- a/fs/jfs/jfs_xtree.c	Fri Oct 24 09:30:35 2003
+++ b/fs/jfs/jfs_xtree.c	Fri Oct 24 09:30:35 2003
 <at>  <at>  -1,5 +1,5  <at>  <at> 
 /*
- *   Copyright (c) International Business Machines Corp., 2000-2002
+ *   Copyright (C) International Business Machines Corp., 2000-2003
  *
  *   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
 <at>  <at>  -60,21 +60,21  <at>  <at> 
 #define XT_PAGE(IP, MP) BT_PAGE(IP, MP, xtpage_t, i_xtroot)

 /* get page buffer for specified block address */
+/* ToDo: Replace this ugly macro with a function */
 #define XT_GETPAGE(IP, BN, MP, SIZE, P, RC)\
 {\
-        BT_GETPAGE(IP, BN, MP, xtpage_t, SIZE, P, RC, i_xtroot)\
-        if (!(RC))\
-        {\
-                if ((le16_to_cpu((P)->header.nextindex) < XTENTRYSTART) ||\
-                    (le16_to_cpu((P)->header.nextindex) > le16_to_cpu((P)->header.maxentry)) ||\
-                    (le16_to_cpu((P)->header.maxentry) > (((BN)==0)?XTROOTMAXSLOT:PSIZE>>L2XTSLOTSIZE)))\
-                {\
-                        jfs_err("XT_GETPAGE: xtree page corrupt");\
+	BT_GETPAGE(IP, BN, MP, xtpage_t, SIZE, P, RC, i_xtroot)\
+	if (!(RC))\
+	{\
+		if ((le16_to_cpu((P)->header.nextindex) < XTENTRYSTART) ||\
+		    (le16_to_cpu((P)->header.nextindex) > le16_to_cpu((P)->header.maxentry)) ||\
+		    (le16_to_cpu((P)->header.maxentry) > (((BN)==0)?XTROOTMAXSLOT:PSIZE>>L2XTSLOTSIZE)))\
+		{\
+			jfs_error((IP)->i_sb, "XT_GETPAGE: xtree page corrupt");\
 			BT_PUTPAGE(MP);\
-			updateSuper((IP)->i_sb, FM_DIRTY);\
 			MP = NULL;\
-                        RC = -EIO;\
-                }\
+			RC = -EIO;\
+		}\
         }\
 }

 <at>  <at>  -1611,14 +1611,21  <at>  <at> 
 	/* there must exist extent to be extended */
 	if ((rc = xtSearch(ip, xoff - 1, &cmp, &btstack, XT_INSERT)))
 		return rc;
-	assert(cmp == 0);
+	if (cmp != 0) {
+		jfs_error(ip->i_sb, "xtExtend: xtSearch did not find extent");
+		return -EIO;
+	}

 	/* retrieve search result */
 	XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);

 	/* extension must be contiguous */
 	xad = &p->xad[index];
-	assert((offsetXAD(xad) + lengthXAD(xad)) == xoff);
+	if ((offsetXAD(xad) + lengthXAD(xad)) != xoff) {
+		XT_PUTPAGE(mp);
+		jfs_error(ip->i_sb, "xtExtend: extension is not contiguous");
+		return -EIO;
+	}

 	/*
 	 * acquire a transaction lock on the leaf page;
 <at>  <at>  -1771,14 +1778,22  <at>  <at> 
 	/* there must exist extent to be tailgated */
 	if ((rc = xtSearch(ip, xoff, &cmp, &btstack, XT_INSERT)))
 		return rc;
-	assert(cmp == 0);
+	if (cmp != 0) {
+		jfs_error(ip->i_sb, "xtTailgate: couldn't find extent");
+		return -EIO;
+	}

 	/* retrieve search result */
 	XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);

 	/* entry found must be last entry */
 	nextindex = le16_to_cpu(p->header.nextindex);
-	assert(index == nextindex - 1);
+	if (index != nextindex - 1) {
+		XT_PUTPAGE(mp);
+		jfs_error(ip->i_sb,
+			  "xtTailgate: the entry found is not the last entry");
+		return -EIO;
+	}

 	BT_MARK_DIRTY(mp, ip);
 	/*
 <at>  <at>  -1941,13 +1956,14  <at>  <at> 
 	nxoff = offsetXAD(nxad);
 	nxlen = lengthXAD(nxad);
 	nxaddr = addressXAD(nxad);
-/*
-printf("xtUpdate: nxflag:0x%x nxoff:0x%lx nxlen:0x%x nxaddr:0x%lx\n",
-        nxad->flag, (ulong)nxoff, nxlen, (ulong)nxaddr);
-*/
+
 	if ((rc = xtSearch(ip, nxoff, &cmp, &btstack, XT_INSERT)))
 		return rc;
-	assert(cmp == 0);
+
+	if (cmp != 0) {
+		jfs_error(ip->i_sb, "xtUpdate: Could not find extent");
+		return -EIO;
+	}

 	/* retrieve search result */
 	XT_GETSEARCH(ip, btstack.top, bn, mp, p, index0);
 <at>  <at>  -1966,14 +1982,15  <at>  <at> 
 	xoff = offsetXAD(xad);
 	xlen = lengthXAD(xad);
 	xaddr = addressXAD(xad);
-/*
-printf("xtUpdate: xflag:0x%x xoff:0x%lx xlen:0x%x xaddr:0x%lx\n",
-        xflag, (ulong)xoff, xlen, (ulong)xaddr);
-*/

 	/* nXAD must be completely contained within XAD */
-	assert(xoff <= nxoff);
-	assert(nxoff + nxlen <= xoff + xlen);
+	if ((xoff > nxoff) ||
+	    (nxoff + nxlen > xoff + xlen)) {
+		XT_PUTPAGE(mp);
+		jfs_error(ip->i_sb,
+			  "xtUpdate: nXAD in not completely contained within XAD");
+		return -EIO;
+	}

 	index = index0;
 	newindex = index + 1;
 <at>  <at>  -2118,7 +2135,11  <at>  <at> 
 	} else if (xoff == nxoff)
 		goto out;

-	assert(xoff < nxoff);
+	if (xoff >= nxoff) {
+		XT_PUTPAGE(mp);
+		jfs_error(ip->i_sb, "xtUpdate: xoff >= nxoff");
+		return -EIO;
+	}
 /* #endif _JFS_WIP_COALESCE */

 	/*
 <at>  <at>  -2135,9 +2156,6  <at>  <at> 

 	/* insert nXAD:recorded */
 	if (nextindex == le16_to_cpu(p->header.maxentry)) {
-/*
-printf("xtUpdate.updateRight.split p:0x%p\n", p);
-*/
 		rootsplit = p->header.flag & BT_ROOT;

 		/* xtSpliUp() unpins leaf pages */
 <at>  <at>  -2248,18 +2266,23  <at>  <at> 

 	/* recompute split pages */
 	if (nextindex == le16_to_cpu(p->header.maxentry)) {
-/*
-printf("xtUpdate: updateRight+Left recompute split pages: p:0x%p\n", p);
-*/
 		XT_PUTPAGE(mp);

 		if ((rc = xtSearch(ip, nxoff, &cmp, &btstack, XT_INSERT)))
 			return rc;
-		assert(cmp == 0);
+		if (cmp != 0) {
+			jfs_error(ip->i_sb, "xtUpdate: xtSearch failed");
+			return -EIO;
+		}

 		/* retrieve search result */
 		XT_GETSEARCH(ip, btstack.top, bn, mp, p, index0);
-		assert(index0 == index);
+		if (index0 != index) {
+			XT_PUTPAGE(mp);
+			jfs_error(ip->i_sb,
+				  "xtUpdate: unexpected value of index");
+			return -EIO;
+		}
 	}

 	/*
 <at>  <at>  -2755,6 +2778,7  <at>  <at> 
  *              txCommit() to commit all the allocation before call
  *              this routine.
  */
+int
 xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad,	/* old XAD */
 	   s64 nxaddr,		/* new xaddr */
 	   int xtype)
 <at>  <at>  -3925,7 +3949,11  <at>  <at> 
 		rc = xtSearch(ip, xoff, &cmp, &btstack, 0);
 		if (rc)
 			return rc;
-		assert(cmp == 0);
+		if (cmp != 0) {
+			jfs_error(ip->i_sb,
+				  "xtTruncate_pmap: did not find extent");
+			return -EIO;
+		}
 		XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
 	} else {
 		/*
diff -Nru a/fs/jfs/namei.c b/fs/jfs/namei.c
--- a/fs/jfs/namei.c	Fri Oct 24 09:30:35 2003
+++ b/fs/jfs/namei.c	Fri Oct 24 09:30:35 2003
 <at>  <at>  -1,6 +1,6  <at>  <at> 
 /*
- *   Copyright (c) International Business Machines Corp., 2000-2002
- *   Portions Copyright (c) Christoph Hellwig, 2001-2002
+ *   Copyright (C) International Business Machines Corp., 2000-2003
+ *   Portions Copyright (C) Christoph Hellwig, 2001-2002
  *
  *   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
 <at>  <at>  -19,6 +19,7  <at>  <at> 

 #include <linux/fs.h>
 #include "jfs_incore.h"
+#include "jfs_superblock.h"
 #include "jfs_inode.h"
 #include "jfs_dinode.h"
 #include "jfs_dmap.h"
 <at>  <at>  -1125,7 +1126,17  <at>  <at> 
 		new_ip->i_nlink--;
 		if (S_ISDIR(new_ip->i_mode)) {
 			new_ip->i_nlink--;
-			assert(new_ip->i_nlink == 0);
+			if (new_ip->i_nlink) {
+				up(&JFS_IP(new_dir)->commit_sem);
+				up(&JFS_IP(old_ip)->commit_sem);
+				if (old_dir != new_dir)
+					up(&JFS_IP(old_dir)->commit_sem);
+				if (!S_ISDIR(old_ip->i_mode) && new_ip)
+					IWRITE_UNLOCK(new_ip);
+				jfs_error(new_ip->i_sb,
+					  "jfs_rename: new_ip->i_nlink != 0");
+				return -EIO;
+			}
 			tblk = tid_to_tblock(tid);
 			tblk->xflag |= COMMIT_DELETE;
 			tblk->ip = new_ip;
diff -Nru a/fs/jfs/resize.c b/fs/jfs/resize.c
--- a/fs/jfs/resize.c	Fri Oct 24 09:30:35 2003
+++ b/fs/jfs/resize.c	Fri Oct 24 09:30:35 2003
 <at>  <at>  -1,5 +1,5  <at>  <at> 
 /*
- *   Copyright (c) International Business Machines  Corp., 2000-2003
+ *   Copyright (C) International Business Machines  Corp., 2000-2003
  *
  *   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
 <at>  <at>  -526,7 +526,7  <at>  <at> 
 	goto resume;

       error_out:
-	updateSuper(sb, FM_DIRTY);
+	jfs_error(sb, "jfs_extendfs");

       resume:
 	/*
diff -Nru a/fs/jfs/super.c b/fs/jfs/super.c
--- a/fs/jfs/super.c	Fri Oct 24 09:30:35 2003
+++ b/fs/jfs/super.c	Fri Oct 24 09:30:35 2003
 <at>  <at>  -1,6 +1,6  <at>  <at> 
 /*
- *   Copyright (c) International Business Machines Corp., 2000-2003
- *   Portions Copyright (c) Christoph Hellwig, 2001-2002
+ *   Copyright (C) International Business Machines Corp., 2000-2003
+ *   Portions Copyright (C) Christoph Hellwig, 2001-2002
  *
  *   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
 <at>  <at>  -77,6 +77,43  <at>  <at> 
 extern wait_queue_head_t jfs_commit_thread_wait;
 extern wait_queue_head_t jfs_sync_thread_wait;

+static void jfs_handle_error(struct super_block *sb)
+{
+	struct jfs_sb_info *sbi = JFS_SBI(sb);
+
+	if (sb->s_flags & MS_RDONLY)
+		return;
+
+	updateSuper(sb, FM_DIRTY);
+
+	if (sbi->flag & JFS_ERR_PANIC)
+		panic("JFS (device %s): panic forced after error\n",
+			bdevname(sb->s_dev));
+	else if (sbi->flag & JFS_ERR_REMOUNT_RO) {
+		jfs_err("ERROR: (device %s): remounting filesystem "
+			"as read-only\n",
+			bdevname(sb->s_dev));
+		sb->s_flags |= MS_RDONLY;
+	} 
+
+	/* nothing is done for continue beyond marking the superblock dirty */
+}
+
+void jfs_error(struct super_block *sb, const char * function, ...)
+{
+	static char error_buf[256];
+	va_list args;
+
+	va_start(args, function);
+	vsprintf(error_buf, function, args);
+	va_end(args);
+
+	printk(KERN_ERR "ERROR: (device %s): %s\n", bdevname(sb->s_dev),
+	       error_buf);
+
+	jfs_handle_error(sb);
+}
+
 static int jfs_statfs(struct super_block *sb, struct statfs *buf)
 {
 	struct jfs_sb_info *sbi = JFS_SBI(sb);
 <at>  <at>  -159,7 +196,26  <at>  <at> 
 			continue;
 		if ((value = strchr(this_char, '=')) != NULL)
 			*value++ = 0;
-		if (!strcmp(this_char, "integrity")) {
+		if (!strcmp(this_char, "errors")) {
+			if (!value || !*value)
+				goto needs_arg;
+			if (!strcmp(value, "continue")) {
+				*flag &= ~JFS_ERR_REMOUNT_RO;
+				*flag &= ~JFS_ERR_PANIC;
+				*flag |= JFS_ERR_CONTINUE;
+			} else if (!strcmp(value, "remount-ro")) {
+				*flag &= ~JFS_ERR_CONTINUE;
+				*flag &= ~JFS_ERR_PANIC;
+				*flag |= JFS_ERR_REMOUNT_RO;
+			} else if (!strcmp(value, "panic")) {
+				*flag &= ~JFS_ERR_CONTINUE;
+				*flag &= ~JFS_ERR_REMOUNT_RO;
+				*flag |= JFS_ERR_PANIC;
+			} else {
+				printk(KERN_ERR "JFS: %s is an invalid error handler\n", value);
+				goto cleanup;
+			}
+		} else if (!strcmp(this_char, "integrity")) {
 			*flag &= ~JFS_NOINTEGRITY;
 		} else 	if (!strcmp(this_char, "nointegrity")) {
 			*flag |= JFS_NOINTEGRITY;
 <at>  <at>  -269,7 +325,9  <at>  <at> 
 	memset(sbi, 0, sizeof (struct jfs_sb_info));
 	sb->u.generic_sbp = sbi;

-	flag = 0;
+	/* initialize the mount flag and determine the default error handler */
+	flag = JFS_ERR_REMOUNT_RO;
+
 	if (!parse_options((char *) data, sb, &newLVSize, &flag)) {
 		kfree(sbi);
 		return NULL;
diff -Nru a/fs/jfs/xattr.c b/fs/jfs/xattr.c
--- a/fs/jfs/xattr.c	Fri Oct 24 09:30:35 2003
+++ b/fs/jfs/xattr.c	Fri Oct 24 09:30:35 2003
 <at>  <at>  -1,6 +1,6  <at>  <at> 
 /*
- *   Copyright (c) International Business Machines  Corp., 2000-2002
- *   Copyright (c) Christoph Hellwig, 2002
+ *   Copyright (C) International Business Machines  Corp., 2000-2003
+ *   Copyright (C) Christoph Hellwig, 2002
  *
  *   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
 <at>  <at>  -20,6 +20,7  <at>  <at> 
 #include <linux/fs.h>
 #include <linux/xattr.h>
 #include "jfs_incore.h"
+#include "jfs_superblock.h"
 #include "jfs_dmap.h"
 #include "jfs_debug.h"
 #include "jfs_dinode.h"
 <at>  <at>  -381,7 +382,10  <at>  <at> 
 		return ea_read_inline(ip, ealist);

 	nbytes = sizeDXD(&ji->ea);
-	assert(nbytes);
+	if (!nbytes) {
+		jfs_error(sb, "ea_read: nbytes is 0");
+		return -EIO;
+	}

 	/* 
 	 * Figure out how many blocks were allocated when this EA list was
 <at>  <at>  -477,7 +481,10  <at>  <at> 
 		}
 		current_blocks = 0;
 	} else {
-		assert(ji->ea.flag & DXD_EXTENT);
+		if (!(ji->ea.flag & DXD_EXTENT)) {
+			jfs_error(sb, "ea_get: invalid ea.flag)");
+			return -EIO;
+		}
 		current_blocks = (ea_size + sb->s_blocksize - 1) >>
 		    sb->s_blocksize_bits;
 	}

Gmane