[PATCH] Improved error handing (2 of 2)
Dave Kleikamp <[email protected]> Fri, 24 Oct 2003 09:39:09 -0500
| Newsgroups | gmane.comp.file-systems.jfs.patches |
|---|---|
| Message-ID | <[email protected]> |
# 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 [email protected] 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 @@ -32,6 +32,10 @@ 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 @@ -1,5 +1,5 @@ /* - * 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 @@ -18,6 +18,7 @@ #include <linux/fs.h> #include "jfs_incore.h" +#include "jfs_superblock.h" #include "jfs_dmap.h" #include "jfs_imap.h" #include "jfs_lock.h" @@ -135,7 +136,6 @@ 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); @@ -383,20 +383,13 @@ /* 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; } /* @@ -480,7 +473,14 @@ 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; @@ -773,7 +773,10 @@ 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. @@ -1120,7 +1123,12 @@ /* 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 @@ -1161,11 +1169,10 @@ 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); } @@ -1430,7 +1437,12 @@ /* 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. @@ -1457,13 +1469,13 @@ 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); } @@ -1512,7 +1524,11 @@ 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 @@ -1547,7 +1563,12 @@ 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); } } @@ -1555,7 +1576,11 @@ /* 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); } @@ -1611,7 +1636,11 @@ /* 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); } @@ -1682,7 +1711,11 @@ /* space found ? */ if (rc) { - assert(lev == level); + if (lev != level) { + jfs_error(bmp->db_ipbmap->i_sb, + "dbFindCtl: dmap inconsistent"); + return -EIO; + } return -ENOSPC; } @@ -1801,7 +1834,13 @@ /* 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. */ @@ -1844,8 +1883,8 @@ /* 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; @@ -1857,8 +1896,8 @@ * 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; } @@ -2153,7 +2192,12 @@ * 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 @@ -2505,7 +2549,11 @@ * 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]; } } @@ -3056,24 +3104,6 @@ /* - * 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 @@ -3359,7 +3389,10 @@ /* 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 */ @@ -3520,7 +3553,9 @@ } } /* 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 @@ -3584,7 +3619,10 @@ 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"); + } } /* @@ -3605,10 +3643,6 @@ 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); -*/ } @@ -3632,9 +3666,6 @@ 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); @@ -3694,10 +3725,6 @@ * 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; @@ -3707,9 +3734,6 @@ /* 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); @@ -4006,7 +4030,7 @@ 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); @@ -4020,7 +4044,9 @@ 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 @@ -1,5 +1,5 @@ /* - * 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 @@ -130,9 +130,8 @@ 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;\ }\ @@ -768,8 +767,7 @@ /* 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; } @@ -3204,11 +3202,12 @@ 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 @@ -1,5 +1,5 @@ /* - * 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 @@ -18,6 +18,7 @@ #include <linux/fs.h> #include "jfs_incore.h" +#include "jfs_superblock.h" #include "jfs_dmap.h" #include "jfs_extent.h" #include "jfs_debug.h" @@ -404,8 +405,10 @@ */ 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 @@ -1,5 +1,5 @@ /* - * 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 @@ -31,6 +31,11 @@ */ /* 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 @@ -1,5 +1,5 @@ /* - * 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 @@ -407,8 +407,7 @@ 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; @@ -645,9 +644,12 @@ 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: @@ -922,12 +924,11 @@ /* 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; } @@ -961,22 +962,28 @@ 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; } /* @@ -1140,7 +1147,6 @@ if ((rc = diIAGRead(imap, inofreefwd, &cmp))) goto error_out; - assert(cmp != NULL); ciagp = (struct iag *) cmp->data; } assert(ciagp != NULL); @@ -1155,7 +1161,6 @@ if ((rc = diIAGRead(imap, inofreeback, &dmp))) goto error_out; - assert(dmp != NULL); diagp = (struct iag *) dmp->data; } assert(diagp != NULL); @@ -1228,7 +1233,9 @@ * 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); @@ -1308,7 +1315,7 @@ 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); @@ -1438,6 +1445,7 @@ iagno = INOTOIAG(inum); if ((rc = diIAGRead(imap, iagno, &mp))) { IREAD_UNLOCK(ipimap); + AG_UNLOCK(imap, agno); return (rc); } iagp = (struct iag *) mp->data; @@ -1540,10 +1548,16 @@ */ 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 @@ -1552,9 +1566,9 @@ 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. */ @@ -1682,8 +1696,7 @@ 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; } @@ -1831,12 +1844,10 @@ /* 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; } @@ -1844,7 +1855,12 @@ * 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; @@ -1854,13 +1870,21 @@ * 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. */ @@ -1943,7 +1967,9 @@ */ 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; } @@ -1951,7 +1977,13 @@ /* 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; } @@ -1959,7 +1991,12 @@ /* 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. @@ -2070,9 +2107,18 @@ /* 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. */ @@ -2176,7 +2222,10 @@ /* 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. */ @@ -2244,7 +2293,12 @@ 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; + } } } @@ -2478,7 +2532,14 @@ /* 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; @@ -2511,7 +2572,6 @@ /* 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 @@ -2738,7 +2798,11 @@ /* 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); @@ -2763,14 +2827,14 @@ * 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); @@ -2782,8 +2846,18 @@ /* 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); } @@ -2822,7 +2896,6 @@ mp->clsn = tblk->clsn; LOGSYNC_UNLOCK(log); } -// bmLazyWrite(mp, log->flag & JFS_COMMIT); write_metapage(mp); return (0); } @@ -2877,7 +2950,12 @@ 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)) { @@ -2889,9 +2967,6 @@ 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)) @@ -2952,8 +3027,12 @@ 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 @@ -1,6 +1,6 @@ /* - * 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 @@ -20,6 +20,7 @@ #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" @@ -291,14 +292,23 @@ 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 @@ -1,5 +1,5 @@ /* - * 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 @@ -108,5 +108,6 @@ 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 @@ -1,6 +1,6 @@ /* - * 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 @@ -1422,7 +1422,6 @@ * 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 @@ -2635,7 +2634,7 @@ * mark filesystem dirty */ if (dirty) - updateSuper(tblk->sb, FM_DIRTY); + jfs_error(tblk->sb, "txAbort"); return; } @@ -2694,7 +2693,7 @@ /* * 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 @@ -1,5 +1,5 @@ /* - * 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 @@ -60,21 +60,21 @@ #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;\ + }\ }\ } @@ -1611,14 +1611,21 @@ /* 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; @@ -1771,14 +1778,22 @@ /* 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); /* @@ -1941,13 +1956,14 @@ 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); @@ -1966,14 +1982,15 @@ 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; @@ -2118,7 +2135,11 @@ } 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 */ /* @@ -2135,9 +2156,6 @@ /* 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 */ @@ -2248,18 +2266,23 @@ /* 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; + } } /* @@ -2755,6 +2778,7 @@ * 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) @@ -3925,7 +3949,11 @@ 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 @@ -1,6 +1,6 @@ /* - * 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 @@ -19,6 +19,7 @@ #include <linux/fs.h> #include "jfs_incore.h" +#include "jfs_superblock.h" #include "jfs_inode.h" #include "jfs_dinode.h" #include "jfs_dmap.h" @@ -1125,7 +1126,17 @@ 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 @@ -1,5 +1,5 @@ /* - * 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 @@ -526,7 +526,7 @@ 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 @@ -1,6 +1,6 @@ /* - * 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 @@ -77,6 +77,43 @@ 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); @@ -159,7 +196,26 @@ 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; @@ -269,7 +325,9 @@ 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 @@ -1,6 +1,6 @@ /* - * 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 @@ -20,6 +20,7 @@ #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" @@ -381,7 +382,10 @@ 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 @@ -477,7 +481,10 @@ } 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; }