Commit 1ec23637 authored by Dave Kleikamp's avatar Dave Kleikamp

Merge jfs@jfs.bkbits.net:linux-2.5

into shaggy.austin.ibm.com:/home/shaggy/bk/jfs-2.5
parents 2ea73f8a 6349fc5a
...@@ -32,6 +32,10 @@ integrity Default. Commit metadata changes to the journal. Use this ...@@ -32,6 +32,10 @@ integrity Default. Commit metadata changes to the journal. Use this
option to remount a volume where the nointegrity option was option to remount a volume where the nointegrity option was
previously specified in order to restore normal behavior. 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: JFS TODO list:
Plans for our near term development items Plans for our near term development items
......
...@@ -34,10 +34,12 @@ int jfs_fsync(struct file *file, struct dentry *dentry, int datasync) ...@@ -34,10 +34,12 @@ int jfs_fsync(struct file *file, struct dentry *dentry, int datasync)
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
int rc = 0; int rc = 0;
if (!(inode->i_state & I_DIRTY)) if (!(inode->i_state & I_DIRTY) ||
return rc; (datasync && !(inode->i_state & I_DIRTY_DATASYNC))) {
if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) /* Make sure committed changes hit the disk */
jfs_flush_journal(JFS_SBI(inode->i_sb)->log, 1);
return rc; return rc;
}
rc |= jfs_commit_inode(inode, 1); rc |= jfs_commit_inode(inode, 1);
......
...@@ -107,14 +107,18 @@ int jfs_commit_inode(struct inode *inode, int wait) ...@@ -107,14 +107,18 @@ int jfs_commit_inode(struct inode *inode, int wait)
void jfs_write_inode(struct inode *inode, int wait) void jfs_write_inode(struct inode *inode, int wait)
{ {
if (test_cflag(COMMIT_Nolink, inode))
return;
/* /*
* If COMMIT_DIRTY is not set, the inode isn't really dirty. * If COMMIT_DIRTY is not set, the inode isn't really dirty.
* It has been committed since the last change, but was still * It has been committed since the last change, but was still
* on the dirty inode list * on the dirty inode list.
*/ */
if (test_cflag(COMMIT_Nolink, inode) || if (!test_cflag(COMMIT_Dirty, inode)) {
!test_cflag(COMMIT_Dirty, inode)) /* Make sure committed changes hit the disk */
jfs_flush_journal(JFS_SBI(inode->i_sb)->log, wait);
return; return;
}
if (jfs_commit_inode(inode, wait)) { if (jfs_commit_inode(inode, wait)) {
jfs_err("jfs_write_inode: jfs_commit_inode failed!"); jfs_err("jfs_write_inode: jfs_commit_inode failed!");
......
/* /*
* 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 * 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 * it under the terms of the GNU General Public License as published by
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include "jfs_incore.h" #include "jfs_incore.h"
#include "jfs_superblock.h"
#include "jfs_dmap.h" #include "jfs_dmap.h"
#include "jfs_imap.h" #include "jfs_imap.h"
#include "jfs_lock.h" #include "jfs_lock.h"
...@@ -134,7 +135,6 @@ static int dbFreeDmap(struct bmap * bmp, struct dmap * dp, s64 blkno, ...@@ -134,7 +135,6 @@ static int dbFreeDmap(struct bmap * bmp, struct dmap * dp, s64 blkno,
static int dbMaxBud(u8 * cp); static int dbMaxBud(u8 * cp);
s64 dbMapFileSizeToMapSize(struct inode *ipbmap); s64 dbMapFileSizeToMapSize(struct inode *ipbmap);
int blkstol2(s64 nb); int blkstol2(s64 nb);
void fsDirty(void);
int cntlz(u32 value); int cntlz(u32 value);
int cnttz(u32 word); int cnttz(u32 word);
...@@ -382,7 +382,15 @@ int dbFree(struct inode *ip, s64 blkno, s64 nblocks) ...@@ -382,7 +382,15 @@ int dbFree(struct inode *ip, s64 blkno, s64 nblocks)
IREAD_LOCK(ipbmap); IREAD_LOCK(ipbmap);
/* block to be freed better be within the mapsize. */ /* block to be freed better be within the mapsize. */
assert(blkno + nblocks <= bmp->db_mapsize); if (blkno + nblocks > bmp->db_mapsize) {
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;
}
/* /*
* free the blocks a dmap at a time. * free the blocks a dmap at a time.
...@@ -465,7 +473,14 @@ dbUpdatePMap(struct inode *ipbmap, ...@@ -465,7 +473,14 @@ dbUpdatePMap(struct inode *ipbmap,
int lsn, difft, diffp; int lsn, difft, diffp;
/* the blocks better be within the mapsize. */ /* 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 */ /* compute delta of transaction lsn from log syncpt */
lsn = tblk->lsn; lsn = tblk->lsn;
...@@ -757,7 +772,10 @@ int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results) ...@@ -757,7 +772,10 @@ int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results)
mapSize = bmp->db_mapsize; mapSize = bmp->db_mapsize;
/* the hint should be within the map */ /* 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 /* if the number of blocks to be allocated is greater than the
* allocation group size, try to allocate anywhere. * allocation group size, try to allocate anywhere.
...@@ -1104,7 +1122,12 @@ int dbExtend(struct inode *ip, s64 blkno, s64 nblocks, s64 addnblocks) ...@@ -1104,7 +1122,12 @@ int dbExtend(struct inode *ip, s64 blkno, s64 nblocks, s64 addnblocks)
/* better be within the file system */ /* better be within the file system */
bmp = sbi->bmap; 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 /* we'll attempt to extend the current allocation in place by
* allocating the additional blocks as the blocks immediately * allocating the additional blocks as the blocks immediately
...@@ -1145,11 +1168,10 @@ int dbExtend(struct inode *ip, s64 blkno, s64 nblocks, s64 addnblocks) ...@@ -1145,11 +1168,10 @@ int dbExtend(struct inode *ip, s64 blkno, s64 nblocks, s64 addnblocks)
DBALLOC(bmp->db_DBmap, bmp->db_mapsize, extblkno, DBALLOC(bmp->db_DBmap, bmp->db_mapsize, extblkno,
addnblocks); addnblocks);
write_metapage(mp); write_metapage(mp);
} else { } else
/* we were not successful */ /* we were not successful */
release_metapage(mp); release_metapage(mp);
assert(rc == -ENOSPC || rc == -EIO);
}
return (rc); return (rc);
} }
...@@ -1414,7 +1436,12 @@ dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results) ...@@ -1414,7 +1436,12 @@ dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results)
/* allocation request should not be for more than the /* allocation request should not be for more than the
* allocation group size. * 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 /* determine the starting block number of the allocation
* group. * group.
...@@ -1441,13 +1468,13 @@ dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results) ...@@ -1441,13 +1468,13 @@ dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results)
if (bmp->db_agsize == BPERDMAP if (bmp->db_agsize == BPERDMAP
|| bmp->db_agfree[agno] == bmp->db_agsize) { || bmp->db_agfree[agno] == bmp->db_agsize) {
rc = dbAllocCtl(bmp, nblocks, l2nb, blkno, results); rc = dbAllocCtl(bmp, nblocks, l2nb, blkno, results);
/* assert(!(rc == -ENOSPC && bmp->db_agfree[agno] == bmp->db_agsize)); */
if ((rc == -ENOSPC) && if ((rc == -ENOSPC) &&
(bmp->db_agfree[agno] == bmp->db_agsize)) { (bmp->db_agfree[agno] == bmp->db_agsize)) {
jfs_err("dbAllocAG: removed assert, but still need to " printk(KERN_ERR "blkno = %Lx, blocks = %Lx\n",
"debug here\nblkno = 0x%Lx, nblocks = 0x%Lx", (unsigned long long) blkno,
(unsigned long long) blkno, (unsigned long long) nblocks);
(unsigned long long) nblocks); jfs_error(bmp->db_ipbmap->i_sb,
"dbAllocAG: dbAllocCtl failed in free AG");
} }
return (rc); return (rc);
} }
...@@ -1496,7 +1523,11 @@ dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results) ...@@ -1496,7 +1523,11 @@ dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results)
break; 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 /* determine the block number within the file system
...@@ -1531,7 +1562,12 @@ dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results) ...@@ -1531,7 +1562,12 @@ dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results)
if ((rc = if ((rc =
dbFindCtl(bmp, l2nb, bmp->db_aglevel - 1, dbFindCtl(bmp, l2nb, bmp->db_aglevel - 1,
&blkno))) { &blkno))) {
assert(rc != -ENOSPC); if (rc == -ENOSPC) {
jfs_error(bmp->db_ipbmap->i_sb,
"dbAllocAG: control page "
"inconsistent");
return -EIO;
}
return (rc); return (rc);
} }
} }
...@@ -1539,7 +1575,11 @@ dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results) ...@@ -1539,7 +1575,11 @@ dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results)
/* allocate the blocks. /* allocate the blocks.
*/ */
rc = dbAllocCtl(bmp, nblocks, l2nb, blkno, results); 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); return (rc);
} }
...@@ -1595,7 +1635,11 @@ static int dbAllocAny(struct bmap * bmp, s64 nblocks, int l2nb, s64 * results) ...@@ -1595,7 +1635,11 @@ static int dbAllocAny(struct bmap * bmp, s64 nblocks, int l2nb, s64 * results)
/* allocate the blocks. /* allocate the blocks.
*/ */
rc = dbAllocCtl(bmp, nblocks, l2nb, blkno, results); 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); return (rc);
} }
...@@ -1666,7 +1710,11 @@ static int dbFindCtl(struct bmap * bmp, int l2nb, int level, s64 * blkno) ...@@ -1666,7 +1710,11 @@ static int dbFindCtl(struct bmap * bmp, int l2nb, int level, s64 * blkno)
/* space found ? /* space found ?
*/ */
if (rc) { if (rc) {
assert(lev == level); if (lev != level) {
jfs_error(bmp->db_ipbmap->i_sb,
"dbFindCtl: dmap inconsistent");
return -EIO;
}
return -ENOSPC; return -ENOSPC;
} }
...@@ -1785,7 +1833,13 @@ dbAllocCtl(struct bmap * bmp, s64 nblocks, int l2nb, s64 blkno, s64 * results) ...@@ -1785,7 +1833,13 @@ dbAllocCtl(struct bmap * bmp, s64 nblocks, int l2nb, s64 blkno, s64 * results)
/* the dmap better be all free. /* 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. /* determine how many blocks to allocate from this dmap.
*/ */
...@@ -1828,8 +1882,8 @@ dbAllocCtl(struct bmap * bmp, s64 nblocks, int l2nb, s64 blkno, s64 * results) ...@@ -1828,8 +1882,8 @@ dbAllocCtl(struct bmap * bmp, s64 nblocks, int l2nb, s64 blkno, s64 * results)
/* could not back out. mark the file system /* could not back out. mark the file system
* to indicate that we have leaked blocks. * to indicate that we have leaked blocks.
*/ */
fsDirty(); /* !!! */ jfs_error(bmp->db_ipbmap->i_sb,
jfs_err("dbAllocCtl: I/O Error: Block Leakage."); "dbAllocCtl: I/O Error: Block Leakage.");
continue; continue;
} }
dp = (struct dmap *) mp->data; dp = (struct dmap *) mp->data;
...@@ -1841,8 +1895,8 @@ dbAllocCtl(struct bmap * bmp, s64 nblocks, int l2nb, s64 blkno, s64 * results) ...@@ -1841,8 +1895,8 @@ dbAllocCtl(struct bmap * bmp, s64 nblocks, int l2nb, s64 blkno, s64 * results)
* to indicate that we have leaked blocks. * to indicate that we have leaked blocks.
*/ */
release_metapage(mp); release_metapage(mp);
fsDirty(); /* !!! */ jfs_error(bmp->db_ipbmap->i_sb,
jfs_err("dbAllocCtl: Block Leakage."); "dbAllocCtl: Block Leakage.");
continue; continue;
} }
...@@ -2137,7 +2191,12 @@ static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno, ...@@ -2137,7 +2191,12 @@ static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
* the allocated words. * the allocated words.
*/ */
for (; nwords > 0; nwords -= nw) { 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 /* determine what the leaf value should be
* updated to as the minimum of the l2 number * updated to as the minimum of the l2 number
...@@ -2489,7 +2548,11 @@ dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level) ...@@ -2489,7 +2548,11 @@ dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level)
* of the maximum free buddy system. * of the maximum free buddy system.
*/ */
assert(level == bmp->db_maxlevel); 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]; bmp->db_maxfreebud = dcp->stree[ROOT];
} }
} }
...@@ -3039,24 +3102,6 @@ int blkstol2(s64 nb) ...@@ -3039,24 +3102,6 @@ int blkstol2(s64 nb)
} }
/*
* NAME: fsDirty()
*
* FUNCTION: xxx
*
* PARAMETERS:
* ipmnt - mount inode
*
* RETURN VALUES:
* none
*/
void fsDirty(void)
{
printk("fsDirty(): bye-bye\n");
assert(0);
}
/* /*
* NAME: dbAllocBottomUp() * NAME: dbAllocBottomUp()
* *
...@@ -3343,7 +3388,10 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks) ...@@ -3343,7 +3388,10 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks)
/* get L2 page */ /* get L2 page */
p = BMAPBLKNO + nbperpage; /* L2 page */ p = BMAPBLKNO + nbperpage; /* L2 page */
l2mp = read_metapage(ipbmap, p, PSIZE, 0); 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; l2dcp = (struct dmapctl *) l2mp->data;
/* compute start L1 */ /* compute start L1 */
...@@ -3504,7 +3552,9 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks) ...@@ -3504,7 +3552,9 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks)
} }
} /* for each L1 in a L2 */ } /* 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 * finalize bmap control page
...@@ -3568,7 +3618,10 @@ void dbFinalizeBmap(struct inode *ipbmap) ...@@ -3568,7 +3618,10 @@ void dbFinalizeBmap(struct inode *ipbmap)
if (bmp->db_agfree[bmp->db_agpref] >= avgfree) if (bmp->db_agfree[bmp->db_agpref] >= avgfree)
break; 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");
}
} }
/* /*
...@@ -3589,10 +3642,6 @@ void dbFinalizeBmap(struct inode *ipbmap) ...@@ -3589,10 +3642,6 @@ void dbFinalizeBmap(struct inode *ipbmap)
n <<= 2; 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);
*/
} }
...@@ -3616,9 +3665,6 @@ printk("bmap: agpref:%d aglevel:%d agheigth:%d agwidth:%d\n", ...@@ -3616,9 +3665,6 @@ printk("bmap: agpref:%d aglevel:%d agheigth:%d agwidth:%d\n",
static int dbInitDmap(struct dmap * dp, s64 Blkno, int nblocks) static int dbInitDmap(struct dmap * dp, s64 Blkno, int nblocks)
{ {
int blkno, w, b, r, nw, nb, i; 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 */ /* starting block number within the dmap */
blkno = Blkno & (BPERDMAP - 1); blkno = Blkno & (BPERDMAP - 1);
...@@ -3678,10 +3724,6 @@ printk("sbh_dmap: in dbInitDmap blkno:%Ld nblocks:%ld\n", Blkno, nblocks); ...@@ -3678,10 +3724,6 @@ printk("sbh_dmap: in dbInitDmap blkno:%Ld nblocks:%ld\n", Blkno, nblocks);
* mark bits following the range to be freed (non-existing * mark bits following the range to be freed (non-existing
* blocks) as allocated (ONES) * blocks) as allocated (ONES)
*/ */
/*
printk("sbh_dmap: in dbInitDmap, preparing to mark unbacked, blkno:%ld nblocks:%ld\n",
blkno, nblocks);
*/
if (blkno == BPERDMAP) if (blkno == BPERDMAP)
goto initTree; goto initTree;
...@@ -3691,9 +3733,6 @@ printk("sbh_dmap: in dbInitDmap, preparing to mark unbacked, blkno:%ld nblocks: ...@@ -3691,9 +3733,6 @@ printk("sbh_dmap: in dbInitDmap, preparing to mark unbacked, blkno:%ld nblocks:
/* does nblocks fall on a 32-bit boundary ? */ /* does nblocks fall on a 32-bit boundary ? */
b = blkno & (DBWORD - 1); b = blkno & (DBWORD - 1);
/*
printk("sbh_dmap: in dbInitDmap, b:%ld w:%ld mask: %lx\n", b, w, (ONES>>b));
*/
if (b) { if (b) {
/* mark a partial word allocated */ /* mark a partial word allocated */
dp->wmap[w] = dp->pmap[w] = cpu_to_le32(ONES >> b); dp->wmap[w] = dp->pmap[w] = cpu_to_le32(ONES >> b);
...@@ -3990,7 +4029,7 @@ static void DBinitmap(s64 size, struct inode *ipbmap, u32 ** results) ...@@ -3990,7 +4029,7 @@ static void DBinitmap(s64 size, struct inode *ipbmap, u32 ** results)
dbmap = (u32 *) xmalloc(npages * 4096, L2PSIZE, kernel_heap); dbmap = (u32 *) xmalloc(npages * 4096, L2PSIZE, kernel_heap);
if (dbmap == NULL) 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) for (n = 0, d = dbmap; n < npages; n++, d += 1024)
bzero(d, 4096); bzero(d, 4096);
...@@ -4004,7 +4043,9 @@ static void DBinitmap(s64 size, struct inode *ipbmap, u32 ** results) ...@@ -4004,7 +4043,9 @@ static void DBinitmap(s64 size, struct inode *ipbmap, u32 ** results)
db_l2nbperpage); db_l2nbperpage);
mp = read_metapage(ipbmap, lblkno, PSIZE, 0); mp = read_metapage(ipbmap, lblkno, PSIZE, 0);
if (mp == NULL) { if (mp == NULL) {
assert(0); jfs_error(ipbmap->i_sb,
"DBinitmap: could not read disk map page");
continue;
} }
dp = (struct dmap *) mp->data; dp = (struct dmap *) mp->data;
......
/* /*
* 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 * 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 * it under the terms of the GNU General Public License as published by
...@@ -130,9 +130,8 @@ struct dtsplit { ...@@ -130,9 +130,8 @@ struct dtsplit {
if (((P)->header.nextindex > (((BN)==0)?DTROOTMAXSLOT:(P)->header.maxslot)) ||\ if (((P)->header.nextindex > (((BN)==0)?DTROOTMAXSLOT:(P)->header.maxslot)) ||\
((BN) && ((P)->header.maxslot > DTPAGEMAXSLOT)))\ ((BN) && ((P)->header.maxslot > DTPAGEMAXSLOT)))\
{\ {\
jfs_err("DT_GETPAGE: dtree page corrupt");\
BT_PUTPAGE(MP);\ BT_PUTPAGE(MP);\
updateSuper((IP)->i_sb, FM_DIRTY);\ jfs_error((IP)->i_sb, "DT_GETPAGE: dtree page corrupt");\
MP = NULL;\ MP = NULL;\
RC = -EIO;\ RC = -EIO;\
}\ }\
...@@ -768,8 +767,7 @@ int dtSearch(struct inode *ip, struct component_name * key, ino_t * data, ...@@ -768,8 +767,7 @@ int dtSearch(struct inode *ip, struct component_name * key, ino_t * data,
/* Something's corrupted, mark filesytem dirty so /* Something's corrupted, mark filesytem dirty so
* chkdsk will fix it. * chkdsk will fix it.
*/ */
jfs_err("stack overrun in dtSearch!"); jfs_error(sb, "stack overrun in dtSearch!");
updateSuper(sb, FM_DIRTY);
rc = -EIO; rc = -EIO;
goto out; goto out;
} }
...@@ -3204,11 +3202,12 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir) ...@@ -3204,11 +3202,12 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
d_namleft -= len; d_namleft -= len;
/* Sanity Check */ /* Sanity Check */
if (d_namleft == 0) { if (d_namleft == 0) {
jfs_err("JFS:Dtree error: ino = " jfs_error(ip->i_sb,
"%ld, bn=%Ld, index = %d", "JFS:Dtree error: ino = "
(long)ip->i_ino,(long long)bn, "%ld, bn=%Ld, index = %d",
i); (long)ip->i_ino,
updateSuper(ip->i_sb, FM_DIRTY); (long long)bn,
i);
goto skip_one; goto skip_one;
} }
len = min(d_namleft, DTSLOTDATALEN); len = min(d_namleft, DTSLOTDATALEN);
......
/* /*
* 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 * 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 * it under the terms of the GNU General Public License as published by
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include "jfs_incore.h" #include "jfs_incore.h"
#include "jfs_superblock.h"
#include "jfs_dmap.h" #include "jfs_dmap.h"
#include "jfs_extent.h" #include "jfs_extent.h"
#include "jfs_debug.h" #include "jfs_debug.h"
...@@ -403,8 +404,10 @@ int extHint(struct inode *ip, s64 offset, xad_t * xp) ...@@ -403,8 +404,10 @@ int extHint(struct inode *ip, s64 offset, xad_t * xp)
*/ */
xp->flag &= XAD_NOTRECORDED; xp->flag &= XAD_NOTRECORDED;
assert(xadl.nxad == 1); if(xadl.nxad != 1 || lengthXAD(xp) != nbperpage) {
assert(lengthXAD(xp) == nbperpage); jfs_error(ip->i_sb, "extHint: corrupt xtree");
return -EIO;
}
return (0); return (0);
} }
......
/* /*
* 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 * 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 * it under the terms of the GNU General Public License as published by
...@@ -32,6 +32,11 @@ ...@@ -32,6 +32,11 @@
/* mount time flag to disable journaling to disk */ /* mount time flag to disable journaling to disk */
#define JFS_NOINTEGRITY 0x00000010 #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) */ /* platform option (conditional compilation) */
#define JFS_AIX 0x80000000 /* AIX support */ #define JFS_AIX 0x80000000 /* AIX support */
/* POSIX name/directory support */ /* POSIX name/directory support */
......
/* /*
* 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 * 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 * it under the terms of the GNU General Public License as published by
...@@ -410,8 +410,7 @@ int diRead(struct inode *ip) ...@@ -410,8 +410,7 @@ int diRead(struct inode *ip)
dp += rel_inode; dp += rel_inode;
if (ip->i_ino != le32_to_cpu(dp->di_number)) { if (ip->i_ino != le32_to_cpu(dp->di_number)) {
jfs_err("diRead: i_ino != di_number"); jfs_error(ip->i_sb, "diRead: i_ino != di_number");
updateSuper(ip->i_sb, FM_DIRTY);
rc = -EIO; rc = -EIO;
} else if (le32_to_cpu(dp->di_nlink) == 0) } else if (le32_to_cpu(dp->di_nlink) == 0)
rc = -ESTALE; rc = -ESTALE;
...@@ -641,9 +640,12 @@ int diWrite(tid_t tid, struct inode *ip) ...@@ -641,9 +640,12 @@ int diWrite(tid_t tid, struct inode *ip)
ino = ip->i_ino & (INOSPERIAG - 1); ino = ip->i_ino & (INOSPERIAG - 1);
assert(lengthPXD(&(jfs_ip->ixpxd)) == if (!addressPXD(&(jfs_ip->ixpxd)) ||
JFS_IP(ipimap)->i_imap->im_nbperiext); (lengthPXD(&(jfs_ip->ixpxd)) !=
assert(addressPXD(&(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: * read the page of disk inode containing the specified inode:
...@@ -918,12 +920,11 @@ int diFree(struct inode *ip) ...@@ -918,12 +920,11 @@ int diFree(struct inode *ip)
/* make sure that the iag is contained within /* make sure that the iag is contained within
* the map. * the map.
*/ */
//assert(iagno < imap->im_nextiag);
if (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); 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; return -EIO;
} }
...@@ -957,22 +958,28 @@ int diFree(struct inode *ip) ...@@ -957,22 +958,28 @@ int diFree(struct inode *ip)
bitno = ino & (INOSPEREXT - 1); bitno = ino & (INOSPEREXT - 1);
mask = HIGHORDER >> bitno; mask = HIGHORDER >> bitno;
assert(le32_to_cpu(iagp->wmap[extno]) & mask); if (!(le32_to_cpu(iagp->wmap[extno]) & mask)) {
#ifdef _STILL_TO_PORT jfs_error(ip->i_sb,
assert((le32_to_cpu(iagp->pmap[extno]) & mask) == 0); "diFree: wmap shows inode already free");
#endif /* _STILL_TO_PORT */ }
assert(addressPXD(&iagp->inoext[extno]));
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. /* compute the bitmap for the extent reflecting the freed inode.
*/ */
bitmap = le32_to_cpu(iagp->wmap[extno]) & ~mask; bitmap = le32_to_cpu(iagp->wmap[extno]) & ~mask;
if (imap->im_agctl[agno].numfree > imap->im_agctl[agno].numinos) { if (imap->im_agctl[agno].numfree > imap->im_agctl[agno].numinos) {
jfs_err("diFree: numfree > numinos");
release_metapage(mp); release_metapage(mp);
IREAD_UNLOCK(ipimap); IREAD_UNLOCK(ipimap);
AG_UNLOCK(imap, agno); AG_UNLOCK(imap, agno);
updateSuper(ip->i_sb, FM_DIRTY); jfs_error(ip->i_sb, "diFree: numfree > numinos");
return -EIO; return -EIO;
} }
/* /*
...@@ -1136,7 +1143,6 @@ int diFree(struct inode *ip) ...@@ -1136,7 +1143,6 @@ int diFree(struct inode *ip)
if ((rc = if ((rc =
diIAGRead(imap, inofreefwd, &cmp))) diIAGRead(imap, inofreefwd, &cmp)))
goto error_out; goto error_out;
assert(cmp != NULL);
ciagp = (struct iag *) cmp->data; ciagp = (struct iag *) cmp->data;
} }
assert(ciagp != NULL); assert(ciagp != NULL);
...@@ -1151,7 +1157,6 @@ int diFree(struct inode *ip) ...@@ -1151,7 +1157,6 @@ int diFree(struct inode *ip)
if ((rc = if ((rc =
diIAGRead(imap, inofreeback, &dmp))) diIAGRead(imap, inofreeback, &dmp)))
goto error_out; goto error_out;
assert(dmp != NULL);
diagp = (struct iag *) dmp->data; diagp = (struct iag *) dmp->data;
} }
assert(diagp != NULL); assert(diagp != NULL);
...@@ -1224,7 +1229,9 @@ int diFree(struct inode *ip) ...@@ -1224,7 +1229,9 @@ int diFree(struct inode *ip)
* the permanent map should have been updated already * the permanent map should have been updated already
* for the inode being freed. * 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; iagp->wmap[extno] = 0;
DBG_DIFREE(imap, inum); DBG_DIFREE(imap, inum);
PXDlength(&iagp->inoext[extno], 0); PXDlength(&iagp->inoext[extno], 0);
...@@ -1304,7 +1311,7 @@ int diFree(struct inode *ip) ...@@ -1304,7 +1311,7 @@ int diFree(struct inode *ip)
iplist[1] = (struct inode *) (size_t)iagno; iplist[1] = (struct inode *) (size_t)iagno;
iplist[2] = (struct inode *) (size_t)extno; 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); txEnd(tid);
...@@ -1434,6 +1441,7 @@ int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip) ...@@ -1434,6 +1441,7 @@ int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip)
iagno = INOTOIAG(inum); iagno = INOTOIAG(inum);
if ((rc = diIAGRead(imap, iagno, &mp))) { if ((rc = diIAGRead(imap, iagno, &mp))) {
IREAD_UNLOCK(ipimap); IREAD_UNLOCK(ipimap);
AG_UNLOCK(imap, agno);
return (rc); return (rc);
} }
iagp = (struct iag *) mp->data; iagp = (struct iag *) mp->data;
...@@ -1536,10 +1544,16 @@ int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip) ...@@ -1536,10 +1544,16 @@ int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip)
*/ */
rem = diFindFree(inosmap, 0); rem = diFindFree(inosmap, 0);
extno = (sword << L2EXTSPERSUM) + rem; extno = (sword << L2EXTSPERSUM) + rem;
rem = rem = diFindFree(le32_to_cpu(iagp->wmap[extno]),
diFindFree(le32_to_cpu 0);
(iagp->wmap[extno]), 0); if (rem >= INOSPEREXT) {
assert(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 /* determine the inode number within the
* iag and allocate the inode from the * iag and allocate the inode from the
...@@ -1548,9 +1562,9 @@ int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip) ...@@ -1548,9 +1562,9 @@ int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip)
ino = (extno << L2INOSPEREXT) + rem; ino = (extno << L2INOSPEREXT) + rem;
rc = diAllocBit(imap, iagp, ino); rc = diAllocBit(imap, iagp, ino);
IREAD_UNLOCK(ipimap); IREAD_UNLOCK(ipimap);
if (rc) { if (rc)
assert(rc == -EIO); assert(rc == -EIO);
} else { else {
/* set the results of the allocation /* set the results of the allocation
* and write the iag. * and write the iag.
*/ */
...@@ -1678,8 +1692,7 @@ diAllocAG(struct inomap * imap, int agno, boolean_t dir, struct inode *ip) ...@@ -1678,8 +1692,7 @@ diAllocAG(struct inomap * imap, int agno, boolean_t dir, struct inode *ip)
numinos = imap->im_agctl[agno].numinos; numinos = imap->im_agctl[agno].numinos;
if (numfree > numinos) { if (numfree > numinos) {
jfs_err("diAllocAG: numfree > numinos"); jfs_error(ip->i_sb, "diAllocAG: numfree > numinos");
updateSuper(ip->i_sb, FM_DIRTY);
return -EIO; return -EIO;
} }
...@@ -1827,12 +1840,10 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip) ...@@ -1827,12 +1840,10 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip)
/* better be free inodes in this iag if it is on the /* better be free inodes in this iag if it is on the
* list. * list.
*/ */
//assert(iagp->nfreeinos);
if (!iagp->nfreeinos) { if (!iagp->nfreeinos) {
jfs_err("diAllocIno: nfreeinos = 0, but iag on freelist"); IREAD_UNLOCK(imap->im_ipimap);
jfs_err(" agno = %d, iagno = %d", agno, iagno); jfs_error(ip->i_sb,
dump_mem("iag", iagp, 64); "diAllocIno: nfreeinos = 0, but iag on freelist");
updateSuper(ip->i_sb, FM_DIRTY);
return -EIO; return -EIO;
} }
...@@ -1840,7 +1851,12 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip) ...@@ -1840,7 +1851,12 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip)
* with free inodes. * with free inodes.
*/ */
for (sword = 0;; sword++) { 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]) if (~iagp->inosmap[sword])
break; break;
...@@ -1850,13 +1866,21 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip) ...@@ -1850,13 +1866,21 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip)
* the extent number. * the extent number.
*/ */
rem = diFindFree(le32_to_cpu(iagp->inosmap[sword]), 0); 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; extno = (sword << L2EXTSPERSUM) + rem;
/* find the first free inode in the extent. /* find the first free inode in the extent.
*/ */
rem = diFindFree(le32_to_cpu(iagp->wmap[extno]), 0); 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. /* compute the inode number within the iag.
*/ */
...@@ -1939,7 +1963,9 @@ static int diAllocExt(struct inomap * imap, int agno, struct inode *ip) ...@@ -1939,7 +1963,9 @@ static int diAllocExt(struct inomap * imap, int agno, struct inode *ip)
*/ */
IREAD_LOCK(imap->im_ipimap); IREAD_LOCK(imap->im_ipimap);
if ((rc = diIAGRead(imap, iagno, &mp))) { 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; iagp = (struct iag *) mp->data;
} }
...@@ -1947,7 +1973,13 @@ static int diAllocExt(struct inomap * imap, int agno, struct inode *ip) ...@@ -1947,7 +1973,13 @@ static int diAllocExt(struct inomap * imap, int agno, struct inode *ip)
/* using the free extent summary map, find a free extent. /* using the free extent summary map, find a free extent.
*/ */
for (sword = 0;; sword++) { 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]) if (~iagp->extsmap[sword])
break; break;
} }
...@@ -1955,7 +1987,12 @@ static int diAllocExt(struct inomap * imap, int agno, struct inode *ip) ...@@ -1955,7 +1987,12 @@ static int diAllocExt(struct inomap * imap, int agno, struct inode *ip)
/* determine the extent number of the free extent. /* determine the extent number of the free extent.
*/ */
rem = diFindFree(le32_to_cpu(iagp->extsmap[sword]), 0); 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; extno = (sword << L2EXTSPERSUM) + rem;
/* initialize the new extent. /* initialize the new extent.
...@@ -2066,9 +2103,18 @@ static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino) ...@@ -2066,9 +2103,18 @@ static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino)
/* the inode should be free and backed. /* the inode should be free and backed.
*/ */
assert((le32_to_cpu(iagp->pmap[extno]) & mask) == 0); if (((le32_to_cpu(iagp->pmap[extno]) & mask) != 0) ||
assert((le32_to_cpu(iagp->wmap[extno]) & mask) == 0); ((le32_to_cpu(iagp->wmap[extno]) & mask) != 0) ||
assert(addressPXD(&iagp->inoext[extno]) != 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. /* mark the inode as allocated in the working map.
*/ */
...@@ -2172,7 +2218,10 @@ static int diNewExt(struct inomap * imap, struct iag * iagp, int extno) ...@@ -2172,7 +2218,10 @@ static int diNewExt(struct inomap * imap, struct iag * iagp, int extno)
/* better have free extents. /* 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. /* get the inode map inode.
*/ */
...@@ -2240,7 +2289,12 @@ static int diNewExt(struct inomap * imap, struct iag * iagp, int extno) ...@@ -2240,7 +2289,12 @@ static int diNewExt(struct inomap * imap, struct iag * iagp, int extno)
goto error_out; goto error_out;
ciagp = (struct iag *) cmp->data; 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;
}
} }
} }
...@@ -2474,7 +2528,14 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp) ...@@ -2474,7 +2528,14 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
/* acquire inode map lock */ /* acquire inode map lock */
IWRITE_LOCK(ipimap); 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 */ /* get the next avaliable iag number */
iagno = imap->im_nextiag; iagno = imap->im_nextiag;
...@@ -2507,7 +2568,6 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp) ...@@ -2507,7 +2568,6 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
/* assign a buffer for the page */ /* assign a buffer for the page */
mp = get_metapage(ipimap, xaddr, PSIZE, 1); mp = get_metapage(ipimap, xaddr, PSIZE, 1);
//bp = bmAssign(ipimap, blkno, xaddr, PSIZE, bmREAD_PAGE);
if (!mp) { if (!mp) {
/* Free the blocks allocated for the iag since it was /* Free the blocks allocated for the iag since it was
* not successfully added to the inode map * not successfully added to the inode map
...@@ -2734,7 +2794,11 @@ diUpdatePMap(struct inode *ipimap, ...@@ -2734,7 +2794,11 @@ diUpdatePMap(struct inode *ipimap,
/* get the iag number containing the inode */ /* get the iag number containing the inode */
iagno = INOTOIAG(inum); iagno = INOTOIAG(inum);
/* make sure that the iag is contained within the map */ /* 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 */ /* read the iag */
IREAD_LOCK(ipimap); IREAD_LOCK(ipimap);
rc = diIAGRead(imap, iagno, &mp); rc = diIAGRead(imap, iagno, &mp);
...@@ -2759,14 +2823,14 @@ diUpdatePMap(struct inode *ipimap, ...@@ -2759,14 +2823,14 @@ diUpdatePMap(struct inode *ipimap,
* of last reference release; * of last reference release;
*/ */
if (!(le32_to_cpu(iagp->wmap[extno]) & mask)) { if (!(le32_to_cpu(iagp->wmap[extno]) & mask)) {
jfs_err("diUpdatePMap: inode %ld not marked as " jfs_error(ipimap->i_sb,
"allocated in wmap!", inum); "diUpdatePMap: inode %ld not marked as "
updateSuper(ipimap->i_sb, FM_DIRTY); "allocated in wmap!", inum);
} }
if (!(le32_to_cpu(iagp->pmap[extno]) & mask)) { if (!(le32_to_cpu(iagp->pmap[extno]) & mask)) {
jfs_err("diUpdatePMap: inode %ld not marked as " jfs_error(ipimap->i_sb,
"allocated in pmap!", inum); "diUpdatePMap: inode %ld not marked as "
updateSuper(ipimap->i_sb, FM_DIRTY); "allocated in pmap!", inum);
} }
/* update the bitmap for the extent of the freed inode */ /* update the bitmap for the extent of the freed inode */
iagp->pmap[extno] &= cpu_to_le32(~mask); iagp->pmap[extno] &= cpu_to_le32(~mask);
...@@ -2778,8 +2842,18 @@ diUpdatePMap(struct inode *ipimap, ...@@ -2778,8 +2842,18 @@ diUpdatePMap(struct inode *ipimap,
/* The inode should be already allocated in the working map /* The inode should be already allocated in the working map
* and should be free in persistent map; * and should be free in persistent map;
*/ */
assert(le32_to_cpu(iagp->wmap[extno]) & mask); if (!(le32_to_cpu(iagp->wmap[extno]) & mask)) {
assert((le32_to_cpu(iagp->pmap[extno]) & mask) == 0); 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 */ /* update the bitmap for the extent of the allocated inode */
iagp->pmap[extno] |= cpu_to_le32(mask); iagp->pmap[extno] |= cpu_to_le32(mask);
} }
...@@ -2817,7 +2891,6 @@ diUpdatePMap(struct inode *ipimap, ...@@ -2817,7 +2891,6 @@ diUpdatePMap(struct inode *ipimap,
mp->clsn = tblk->clsn; mp->clsn = tblk->clsn;
LOGSYNC_UNLOCK(log); LOGSYNC_UNLOCK(log);
} }
// bmLazyWrite(mp, log->flag & JFS_COMMIT);
write_metapage(mp); write_metapage(mp);
return (0); return (0);
} }
...@@ -2872,7 +2945,12 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap) ...@@ -2872,7 +2945,12 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap)
continue; continue;
} }
iagp = (struct iag *) bp->data; 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 */ /* leave free iag in the free iag list */
if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG)) { if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG)) {
...@@ -2884,9 +2962,6 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap) ...@@ -2884,9 +2962,6 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap)
agstart = le64_to_cpu(iagp->agstart); agstart = le64_to_cpu(iagp->agstart);
/* iagp->agstart = agstart & ~(mp->db_agsize - 1); */ /* iagp->agstart = agstart & ~(mp->db_agsize - 1); */
n = agstart >> mp->db_agl2size; n = agstart >> mp->db_agl2size;
/*
printf("diExtendFS: iag:%d agstart:%Ld agno:%d\n", i, agstart, n);
*/
/* compute backed inodes */ /* compute backed inodes */
numinos = (EXTSPERIAG - le32_to_cpu(iagp->nfreeexts)) numinos = (EXTSPERIAG - le32_to_cpu(iagp->nfreeexts))
...@@ -2947,8 +3022,12 @@ printf("diExtendFS: iag:%d agstart:%Ld agno:%d\n", i, agstart, n); ...@@ -2947,8 +3022,12 @@ printf("diExtendFS: iag:%d agstart:%Ld agno:%d\n", i, agstart, n);
write_metapage(bp); write_metapage(bp);
} }
ASSERT(xnuminos == atomic_read(&imap->im_numinos) && if (xnuminos != atomic_read(&imap->im_numinos) ||
xnumfree == atomic_read(&imap->im_numfree)); xnumfree != atomic_read(&imap->im_numfree)) {
jfs_error(ipimap->i_sb,
"diExtendFs: numinos or numfree incorrect");
return -EIO;
}
return rcx; return rcx;
} }
......
/* /*
* Copyright (c) International Business Machines Corp., 2000-2002 * Copyright (C) International Business Machines Corp., 2000-2003
* Portions Copyright (c) Christoph Hellwig, 2001-2002 * Portions Copyright (C) Christoph Hellwig, 2001-2002
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/mempool.h> #include <linux/mempool.h>
#include "jfs_incore.h" #include "jfs_incore.h"
#include "jfs_superblock.h"
#include "jfs_filsys.h" #include "jfs_filsys.h"
#include "jfs_metapage.h" #include "jfs_metapage.h"
#include "jfs_txnmgr.h" #include "jfs_txnmgr.h"
...@@ -233,14 +234,23 @@ struct metapage *__get_metapage(struct inode *inode, unsigned long lblock, ...@@ -233,14 +234,23 @@ struct metapage *__get_metapage(struct inode *inode, unsigned long lblock,
if (mp) { if (mp) {
page_found: page_found:
if (test_bit(META_discard, &mp->flag)) { if (test_bit(META_discard, &mp->flag)) {
assert(new); /* It's okay to reuse a discarded if (!new) {
* if we expect it to be empty spin_unlock(&meta_lock);
*/ jfs_error(inode->i_sb,
"__get_metapage: using a "
"discarded metapage");
return NULL;
}
clear_bit(META_discard, &mp->flag); clear_bit(META_discard, &mp->flag);
} }
mp->count++; mp->count++;
jfs_info("__get_metapage: found 0x%p, in hash", mp); 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); lock_metapage(mp);
spin_unlock(&meta_lock); spin_unlock(&meta_lock);
} else { } else {
......
/* /*
* 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 * 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 * it under the terms of the GNU General Public License as published by
...@@ -108,5 +108,6 @@ struct jfs_superblock { ...@@ -108,5 +108,6 @@ struct jfs_superblock {
extern int readSuper(struct super_block *, struct buffer_head **); extern int readSuper(struct super_block *, struct buffer_head **);
extern int updateSuper(struct super_block *, uint); extern int updateSuper(struct super_block *, uint);
extern void jfs_error(struct super_block *, const char *, ...);
#endif /*_H_JFS_SUPERBLOCK */ #endif /*_H_JFS_SUPERBLOCK */
/* /*
* Copyright (c) International Business Machines Corp., 2000-2003 * Copyright (C) International Business Machines Corp., 2000-2003
* Portions Copyright (c) Christoph Hellwig, 2001-2002 * Portions Copyright (C) Christoph Hellwig, 2001-2002
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -1442,7 +1442,6 @@ int diLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, ...@@ -1442,7 +1442,6 @@ int diLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
* page is not itself logged, to prevent pageout of the map * page is not itself logged, to prevent pageout of the map
* page before the log; * page before the log;
*/ */
assert(tlck->type & tlckFREE);
/* log LOG_NOREDOINOEXT of the freed inode extent for /* log LOG_NOREDOINOEXT of the freed inode extent for
* logredo() to start NoRedoPage filters, and to update * logredo() to start NoRedoPage filters, and to update
...@@ -2655,7 +2654,7 @@ void txAbort(tid_t tid, int dirty) ...@@ -2655,7 +2654,7 @@ void txAbort(tid_t tid, int dirty)
* mark filesystem dirty * mark filesystem dirty
*/ */
if (dirty) if (dirty)
updateSuper(tblk->sb, FM_DIRTY); jfs_error(tblk->sb, "txAbort");
return; return;
} }
...@@ -2714,7 +2713,7 @@ static void txAbortCommit(struct commit * cd) ...@@ -2714,7 +2713,7 @@ static void txAbortCommit(struct commit * cd)
/* /*
* mark filesystem dirty * mark filesystem dirty
*/ */
updateSuper(cd->sb, FM_DIRTY); jfs_error(cd->sb, "txAbortCommit");
} }
......
/* /*
* 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 * 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 * it under the terms of the GNU General Public License as published by
...@@ -60,21 +60,21 @@ ...@@ -60,21 +60,21 @@
#define XT_PAGE(IP, MP) BT_PAGE(IP, MP, xtpage_t, i_xtroot) #define XT_PAGE(IP, MP) BT_PAGE(IP, MP, xtpage_t, i_xtroot)
/* get page buffer for specified block address */ /* get page buffer for specified block address */
/* ToDo: Replace this ugly macro with a function */
#define XT_GETPAGE(IP, BN, MP, SIZE, P, RC)\ #define XT_GETPAGE(IP, BN, MP, SIZE, P, RC)\
{\ {\
BT_GETPAGE(IP, BN, MP, xtpage_t, SIZE, P, RC, i_xtroot)\ BT_GETPAGE(IP, BN, MP, xtpage_t, SIZE, P, RC, i_xtroot)\
if (!(RC))\ if (!(RC))\
{\ {\
if ((le16_to_cpu((P)->header.nextindex) < XTENTRYSTART) ||\ 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.nextindex) > le16_to_cpu((P)->header.maxentry)) ||\
(le16_to_cpu((P)->header.maxentry) > (((BN)==0)?XTROOTMAXSLOT:PSIZE>>L2XTSLOTSIZE)))\ (le16_to_cpu((P)->header.maxentry) > (((BN)==0)?XTROOTMAXSLOT:PSIZE>>L2XTSLOTSIZE)))\
{\ {\
jfs_err("XT_GETPAGE: xtree page corrupt");\ jfs_error((IP)->i_sb, "XT_GETPAGE: xtree page corrupt");\
BT_PUTPAGE(MP);\ BT_PUTPAGE(MP);\
updateSuper((IP)->i_sb, FM_DIRTY);\
MP = NULL;\ MP = NULL;\
RC = -EIO;\ RC = -EIO;\
}\ }\
}\ }\
} }
...@@ -1611,14 +1611,21 @@ int xtExtend(tid_t tid, /* transaction id */ ...@@ -1611,14 +1611,21 @@ int xtExtend(tid_t tid, /* transaction id */
/* there must exist extent to be extended */ /* there must exist extent to be extended */
if ((rc = xtSearch(ip, xoff - 1, &cmp, &btstack, XT_INSERT))) if ((rc = xtSearch(ip, xoff - 1, &cmp, &btstack, XT_INSERT)))
return rc; return rc;
assert(cmp == 0); if (cmp != 0) {
jfs_error(ip->i_sb, "xtExtend: xtSearch did not find extent");
return -EIO;
}
/* retrieve search result */ /* retrieve search result */
XT_GETSEARCH(ip, btstack.top, bn, mp, p, index); XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
/* extension must be contiguous */ /* extension must be contiguous */
xad = &p->xad[index]; 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; * acquire a transaction lock on the leaf page;
...@@ -1771,14 +1778,22 @@ printf("xtTailgate: nxoff:0x%lx nxlen:0x%x nxaddr:0x%lx\n", ...@@ -1771,14 +1778,22 @@ printf("xtTailgate: nxoff:0x%lx nxlen:0x%x nxaddr:0x%lx\n",
/* there must exist extent to be tailgated */ /* there must exist extent to be tailgated */
if ((rc = xtSearch(ip, xoff, &cmp, &btstack, XT_INSERT))) if ((rc = xtSearch(ip, xoff, &cmp, &btstack, XT_INSERT)))
return rc; return rc;
assert(cmp == 0); if (cmp != 0) {
jfs_error(ip->i_sb, "xtTailgate: couldn't find extent");
return -EIO;
}
/* retrieve search result */ /* retrieve search result */
XT_GETSEARCH(ip, btstack.top, bn, mp, p, index); XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
/* entry found must be last entry */ /* entry found must be last entry */
nextindex = le16_to_cpu(p->header.nextindex); 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); BT_MARK_DIRTY(mp, ip);
/* /*
...@@ -1941,13 +1956,14 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad) ...@@ -1941,13 +1956,14 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad)
nxoff = offsetXAD(nxad); nxoff = offsetXAD(nxad);
nxlen = lengthXAD(nxad); nxlen = lengthXAD(nxad);
nxaddr = addressXAD(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))) if ((rc = xtSearch(ip, nxoff, &cmp, &btstack, XT_INSERT)))
return rc; return rc;
assert(cmp == 0);
if (cmp != 0) {
jfs_error(ip->i_sb, "xtUpdate: Could not find extent");
return -EIO;
}
/* retrieve search result */ /* retrieve search result */
XT_GETSEARCH(ip, btstack.top, bn, mp, p, index0); XT_GETSEARCH(ip, btstack.top, bn, mp, p, index0);
...@@ -1966,14 +1982,15 @@ printf("xtUpdate: nxflag:0x%x nxoff:0x%lx nxlen:0x%x nxaddr:0x%lx\n", ...@@ -1966,14 +1982,15 @@ printf("xtUpdate: nxflag:0x%x nxoff:0x%lx nxlen:0x%x nxaddr:0x%lx\n",
xoff = offsetXAD(xad); xoff = offsetXAD(xad);
xlen = lengthXAD(xad); xlen = lengthXAD(xad);
xaddr = addressXAD(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 */ /* nXAD must be completely contained within XAD */
assert(xoff <= nxoff); if ((xoff > nxoff) ||
assert(nxoff + nxlen <= xoff + xlen); (nxoff + nxlen > xoff + xlen)) {
XT_PUTPAGE(mp);
jfs_error(ip->i_sb,
"xtUpdate: nXAD in not completely contained within XAD");
return -EIO;
}
index = index0; index = index0;
newindex = index + 1; newindex = index + 1;
...@@ -2118,7 +2135,11 @@ printf("xtUpdate: xflag:0x%x xoff:0x%lx xlen:0x%x xaddr:0x%lx\n", ...@@ -2118,7 +2135,11 @@ printf("xtUpdate: xflag:0x%x xoff:0x%lx xlen:0x%x xaddr:0x%lx\n",
} else if (xoff == nxoff) } else if (xoff == nxoff)
goto out; 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 */ /* #endif _JFS_WIP_COALESCE */
/* /*
...@@ -2135,9 +2156,6 @@ printf("xtUpdate: xflag:0x%x xoff:0x%lx xlen:0x%x xaddr:0x%lx\n", ...@@ -2135,9 +2156,6 @@ printf("xtUpdate: xflag:0x%x xoff:0x%lx xlen:0x%x xaddr:0x%lx\n",
/* insert nXAD:recorded */ /* insert nXAD:recorded */
if (nextindex == le16_to_cpu(p->header.maxentry)) { if (nextindex == le16_to_cpu(p->header.maxentry)) {
/*
printf("xtUpdate.updateRight.split p:0x%p\n", p);
*/
rootsplit = p->header.flag & BT_ROOT; rootsplit = p->header.flag & BT_ROOT;
/* xtSpliUp() unpins leaf pages */ /* xtSpliUp() unpins leaf pages */
...@@ -2248,18 +2266,23 @@ printf("xtUpdate.updateRight.split p:0x%p\n", p); ...@@ -2248,18 +2266,23 @@ printf("xtUpdate.updateRight.split p:0x%p\n", p);
/* recompute split pages */ /* recompute split pages */
if (nextindex == le16_to_cpu(p->header.maxentry)) { if (nextindex == le16_to_cpu(p->header.maxentry)) {
/*
printf("xtUpdate: updateRight+Left recompute split pages: p:0x%p\n", p);
*/
XT_PUTPAGE(mp); XT_PUTPAGE(mp);
if ((rc = xtSearch(ip, nxoff, &cmp, &btstack, XT_INSERT))) if ((rc = xtSearch(ip, nxoff, &cmp, &btstack, XT_INSERT)))
return rc; return rc;
assert(cmp == 0); if (cmp != 0) {
jfs_error(ip->i_sb, "xtUpdate: xtSearch failed");
return -EIO;
}
/* retrieve search result */ /* retrieve search result */
XT_GETSEARCH(ip, btstack.top, bn, mp, p, index0); 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 @@ xtDeleteUp(tid_t tid, struct inode *ip, ...@@ -2755,6 +2778,7 @@ xtDeleteUp(tid_t tid, struct inode *ip,
* txCommit() to commit all the allocation before call * txCommit() to commit all the allocation before call
* this routine. * this routine.
*/ */
int
xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
s64 nxaddr, /* new xaddr */ s64 nxaddr, /* new xaddr */
int xtype) int xtype)
...@@ -3925,7 +3949,11 @@ s64 xtTruncate_pmap(tid_t tid, struct inode *ip, s64 committed_size) ...@@ -3925,7 +3949,11 @@ s64 xtTruncate_pmap(tid_t tid, struct inode *ip, s64 committed_size)
rc = xtSearch(ip, xoff, &cmp, &btstack, 0); rc = xtSearch(ip, xoff, &cmp, &btstack, 0);
if (rc) if (rc)
return 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); XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
} else { } else {
/* /*
......
/* /*
* Copyright (c) International Business Machines Corp., 2000-2002 * Copyright (C) International Business Machines Corp., 2000-2003
* Portions Copyright (c) Christoph Hellwig, 2001-2002 * Portions Copyright (C) Christoph Hellwig, 2001-2002
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include "jfs_incore.h" #include "jfs_incore.h"
#include "jfs_superblock.h"
#include "jfs_inode.h" #include "jfs_inode.h"
#include "jfs_dinode.h" #include "jfs_dinode.h"
#include "jfs_dmap.h" #include "jfs_dmap.h"
...@@ -1138,7 +1139,17 @@ int jfs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1138,7 +1139,17 @@ int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
new_ip->i_nlink--; new_ip->i_nlink--;
if (S_ISDIR(new_ip->i_mode)) { if (S_ISDIR(new_ip->i_mode)) {
new_ip->i_nlink--; 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 = tid_to_tblock(tid);
tblk->xflag |= COMMIT_DELETE; tblk->xflag |= COMMIT_DELETE;
tblk->ip = new_ip; tblk->ip = new_ip;
......
/* /*
* 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 * 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 * it under the terms of the GNU General Public License as published by
...@@ -523,7 +523,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize) ...@@ -523,7 +523,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
goto resume; goto resume;
error_out: error_out:
updateSuper(sb, FM_DIRTY); jfs_error(sb, "jfs_extendfs");
resume: resume:
/* /*
......
/* /*
* Copyright (c) International Business Machines Corp., 2000-2003 * Copyright (C) International Business Machines Corp., 2000-2003
* Portions Copyright (c) Christoph Hellwig, 2001-2002 * Portions Copyright (C) Christoph Hellwig, 2001-2002
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -85,6 +85,42 @@ extern wait_queue_head_t jfs_IO_thread_wait; ...@@ -85,6 +85,42 @@ extern wait_queue_head_t jfs_IO_thread_wait;
extern wait_queue_head_t jfs_commit_thread_wait; extern wait_queue_head_t jfs_commit_thread_wait;
extern wait_queue_head_t jfs_sync_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",
sb->s_id);
else if (sbi->flag & JFS_ERR_REMOUNT_RO) {
jfs_err("ERROR: (device %s): remounting filesystem "
"as read-only\n",
sb->s_id);
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", sb->s_id, error_buf);
jfs_handle_error(sb);
}
static struct inode *jfs_alloc_inode(struct super_block *sb) static struct inode *jfs_alloc_inode(struct super_block *sb)
{ {
struct jfs_inode_info *jfs_inode; struct jfs_inode_info *jfs_inode;
...@@ -167,7 +203,7 @@ static void jfs_put_super(struct super_block *sb) ...@@ -167,7 +203,7 @@ static void jfs_put_super(struct super_block *sb)
enum { enum {
Opt_integrity, Opt_nointegrity, Opt_iocharset, Opt_resize, Opt_integrity, Opt_nointegrity, Opt_iocharset, Opt_resize,
Opt_ignore, Opt_err, Opt_errors, Opt_ignore, Opt_err,
}; };
static match_table_t tokens = { static match_table_t tokens = {
...@@ -175,6 +211,7 @@ static match_table_t tokens = { ...@@ -175,6 +211,7 @@ static match_table_t tokens = {
{Opt_nointegrity, "nointegrity"}, {Opt_nointegrity, "nointegrity"},
{Opt_iocharset, "iocharset=%s"}, {Opt_iocharset, "iocharset=%s"},
{Opt_resize, "resize=%u"}, {Opt_resize, "resize=%u"},
{Opt_errors, "errors=%s"},
{Opt_ignore, "noquota"}, {Opt_ignore, "noquota"},
{Opt_ignore, "quota"}, {Opt_ignore, "quota"},
{Opt_ignore, "usrquota"}, {Opt_ignore, "usrquota"},
...@@ -234,6 +271,31 @@ static int parse_options(char *options, struct super_block *sb, s64 *newLVSize, ...@@ -234,6 +271,31 @@ static int parse_options(char *options, struct super_block *sb, s64 *newLVSize,
*newLVSize = simple_strtoull(resize, &resize, 0); *newLVSize = simple_strtoull(resize, &resize, 0);
break; break;
} }
case Opt_errors:
{
char *errors = args[0].from;
if (!errors || !*errors)
goto cleanup;
if (!strcmp(errors, "continue")) {
*flag &= ~JFS_ERR_REMOUNT_RO;
*flag &= ~JFS_ERR_PANIC;
*flag |= JFS_ERR_CONTINUE;
} else if (!strcmp(errors, "remount-ro")) {
*flag &= ~JFS_ERR_CONTINUE;
*flag &= ~JFS_ERR_PANIC;
*flag |= JFS_ERR_REMOUNT_RO;
} else if (!strcmp(errors, "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",
errors);
goto cleanup;
}
break;
}
default: default:
printk("jfs: Unrecognized mount option \"%s\" " printk("jfs: Unrecognized mount option \"%s\" "
" or missing value\n", p); " or missing value\n", p);
...@@ -316,7 +378,9 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -316,7 +378,9 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
memset(sbi, 0, sizeof (struct jfs_sb_info)); memset(sbi, 0, sizeof (struct jfs_sb_info));
sb->s_fs_info = sbi; sb->s_fs_info = 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)) { if (!parse_options((char *) data, sb, &newLVSize, &flag)) {
kfree(sbi); kfree(sbi);
return -EINVAL; return -EINVAL;
......
/* /*
* Copyright (c) International Business Machines Corp., 2000-2002 * Copyright (C) International Business Machines Corp., 2000-2003
* Copyright (c) Christoph Hellwig, 2002 * Copyright (C) Christoph Hellwig, 2002
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/xattr.h> #include <linux/xattr.h>
#include "jfs_incore.h" #include "jfs_incore.h"
#include "jfs_superblock.h"
#include "jfs_dmap.h" #include "jfs_dmap.h"
#include "jfs_debug.h" #include "jfs_debug.h"
#include "jfs_dinode.h" #include "jfs_dinode.h"
...@@ -381,7 +382,10 @@ static int ea_read(struct inode *ip, struct jfs_ea_list *ealist) ...@@ -381,7 +382,10 @@ static int ea_read(struct inode *ip, struct jfs_ea_list *ealist)
return ea_read_inline(ip, ealist); return ea_read_inline(ip, ealist);
nbytes = sizeDXD(&ji->ea); 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 * Figure out how many blocks were allocated when this EA list was
...@@ -477,7 +481,10 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size) ...@@ -477,7 +481,10 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size)
} }
current_blocks = 0; current_blocks = 0;
} else { } 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) >> current_blocks = (ea_size + sb->s_blocksize - 1) >>
sb->s_blocksize_bits; sb->s_blocksize_bits;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment