From ac17b8b57013a3e38d1958f66a218f15659e5752 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Mon, 3 Oct 2005 15:32:11 -0500 Subject: JFS: make special inodes play nicely with page balancing This patch fixes up a few problems with jfs's reserved inodes. 1. There is no need for the jfs code setting the I_DIRTY bits in i_state. I am ashamed that the code ever did this, and surprised it hasn't been noticed until now. 2. Make sure special inodes are on an inode hash list. If the inodes are unhashed, __mark_inode_dirty will fail to put the inode on the superblock's dirty list, and the data will not be flushed under memory pressure. 3. Force writing journal data to disk when metapage_writepage is unable to write a metadata page due to pending journal I/O. Signed-off-by: Dave Kleikamp --- fs/jfs/jfs_dmap.c | 1 - fs/jfs/jfs_imap.c | 10 ++++++++-- fs/jfs/jfs_metapage.c | 6 ++++++ fs/jfs/jfs_txnmgr.c | 2 -- fs/jfs/super.c | 1 + 5 files changed, 15 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c index eadf319..51c02bf 100644 --- a/fs/jfs/jfs_dmap.c +++ b/fs/jfs/jfs_dmap.c @@ -305,7 +305,6 @@ int dbSync(struct inode *ipbmap) filemap_fdatawrite(ipbmap->i_mapping); filemap_fdatawait(ipbmap->i_mapping); - ipbmap->i_state |= I_DIRTY; diWriteSpecial(ipbmap, 0); return (0); diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index 4021d46..28201b1 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c @@ -57,6 +57,12 @@ #include "jfs_debug.h" /* + * __mark_inode_dirty expects inodes to be hashed. Since we don't want + * special inodes in the fileset inode space, we hash them to a dummy head + */ +static HLIST_HEAD(aggregate_hash); + +/* * imap locks */ /* iag free list lock */ @@ -491,6 +497,8 @@ struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary) /* release the page */ release_metapage(mp); + hlist_add_head(&ip->i_hash, &aggregate_hash); + return (ip); } @@ -514,8 +522,6 @@ void diWriteSpecial(struct inode *ip, int secondary) ino_t inum = ip->i_ino; struct metapage *mp; - ip->i_state &= ~I_DIRTY; - if (secondary) address = addressPXD(&sbi->ait2) >> sbi->l2nbperpage; else diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index 13d7e3f..c81c643 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c @@ -395,6 +395,12 @@ static int metapage_writepage(struct page *page, struct writeback_control *wbc) if (mp->nohomeok && !test_bit(META_forcewrite, &mp->flag)) { redirty = 1; + /* + * Make sure this page isn't blocked indefinitely. + * If the journal isn't undergoing I/O, push it + */ + if (mp->log && !(mp->log->cflag & logGC_PAGEOUT)) + jfs_flush_journal(mp->log, 0); continue; } diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c index 9b71ed2..b660c93 100644 --- a/fs/jfs/jfs_txnmgr.c +++ b/fs/jfs/jfs_txnmgr.c @@ -2396,7 +2396,6 @@ static void txUpdateMap(struct tblock * tblk) */ if (tblk->xflag & COMMIT_CREATE) { diUpdatePMap(ipimap, tblk->ino, FALSE, tblk); - ipimap->i_state |= I_DIRTY; /* update persistent block allocation map * for the allocation of inode extent; */ @@ -2407,7 +2406,6 @@ static void txUpdateMap(struct tblock * tblk) } else if (tblk->xflag & COMMIT_DELETE) { ip = tblk->u.ip; diUpdatePMap(ipimap, ip->i_ino, TRUE, tblk); - ipimap->i_state |= I_DIRTY; iput(ip); } } diff --git a/fs/jfs/super.c b/fs/jfs/super.c index 71bc34b..4226af3 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c @@ -442,6 +442,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) inode->i_nlink = 1; inode->i_size = sb->s_bdev->bd_inode->i_size; inode->i_mapping->a_ops = &jfs_metapage_aops; + insert_inode_hash(inode); mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS); sbi->direct_inode = inode; -- cgit v1.1 From b6a47fd8ff08a9d5cd279cdb8d97a619983575fa Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Tue, 11 Oct 2005 09:06:59 -0500 Subject: JFS: Corrupted block map should not cause trap Replace assert statements with better error handling. Signed-off-by: Dave Kleikamp --- fs/jfs/jfs_dmap.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c index 51c02bf..68000a5 100644 --- a/fs/jfs/jfs_dmap.c +++ b/fs/jfs/jfs_dmap.c @@ -74,7 +74,7 @@ static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno, int nblocks); static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval); -static void dbBackSplit(dmtree_t * tp, int leafno); +static int dbBackSplit(dmtree_t * tp, int leafno); static int dbJoin(dmtree_t * tp, int leafno, int newval); static void dbAdjTree(dmtree_t * tp, int leafno, int newval); static int dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, @@ -2466,7 +2466,9 @@ dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level) * that it is at the front of a binary buddy system. */ if (oldval == NOFREE) { - dbBackSplit((dmtree_t *) dcp, leafno); + rc = dbBackSplit((dmtree_t *) dcp, leafno); + if (rc) + return rc; oldval = dcp->stree[ti]; } dbSplit((dmtree_t *) dcp, leafno, dcp->budmin, newval); @@ -2626,7 +2628,7 @@ static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval) * * serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit; */ -static void dbBackSplit(dmtree_t * tp, int leafno) +static int dbBackSplit(dmtree_t * tp, int leafno) { int budsz, bud, w, bsz, size; int cursz; @@ -2661,7 +2663,10 @@ static void dbBackSplit(dmtree_t * tp, int leafno) */ for (w = leafno, bsz = budsz;; bsz <<= 1, w = (w < bud) ? w : bud) { - assert(bsz < le32_to_cpu(tp->dmt_nleafs)); + if (bsz >= le32_to_cpu(tp->dmt_nleafs)) { + jfs_err("JFS: block map error in dbBackSplit"); + return -EIO; + } /* determine the buddy. */ @@ -2680,7 +2685,11 @@ static void dbBackSplit(dmtree_t * tp, int leafno) } } - assert(leaf[leafno] == size); + if (leaf[leafno] != size) { + jfs_err("JFS: wrong leaf value in dbBackSplit"); + return -EIO; + } + return 0; } -- cgit v1.1 From 7038f1cbac899654cf0515e60dbe3e44d58271de Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Fri, 28 Oct 2005 13:27:40 -0500 Subject: JFS: make sure right-most xtree pages have header.next set to zero The xtTruncate code was only doing this for leaf pages. When a file is horribly fragmented, we may truncate a file leaving an internal page with an invalid head.next field, which may cause a stale page to be referenced. Signed-off-by: Dave Kleikamp --- fs/jfs/jfs_xtree.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'fs') diff --git a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c index a7fe2f2..e72f4eb 100644 --- a/fs/jfs/jfs_xtree.c +++ b/fs/jfs/jfs_xtree.c @@ -3516,16 +3516,10 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag) /* process entries backward from last index */ index = le16_to_cpu(p->header.nextindex) - 1; - if (p->header.flag & BT_INTERNAL) - goto getChild; - - /* - * leaf page - */ - /* Since this is the rightmost leaf, and we may have already freed - * a page that was formerly to the right, let's make sure that the - * next pointer is zero. + /* Since this is the rightmost page at this level, and we may have + * already freed a page that was formerly to the right, let's make + * sure that the next pointer is zero. */ if (p->header.next) { if (log) @@ -3539,6 +3533,12 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag) p->header.next = 0; } + if (p->header.flag & BT_INTERNAL) + goto getChild; + + /* + * leaf page + */ freed = 0; /* does region covered by leaf page precede Teof ? */ -- cgit v1.1