From a685e26fff387db350966f88eaad515bf41c4705 Mon Sep 17 00:00:00 2001 From: Evgeniy Dushistov Date: Mon, 29 Jan 2007 13:19:54 -0800 Subject: [PATCH] ufs: alloc metadata null page fix These series of patches result of UFS1 write support stress testing, like running fsx-linux, untar and build linux kernel etc We pass from ufs::get_block_t to levels below: pointer to the current page, to make possible things like reallocation of blocks on the fly, and we also uses this pointer for indication, what actually we allocate data block or meta data block, but currently we make decision about what we allocate on the wrong level, this may and cause oops if we allocate blocks in some special order. Signed-off-by: Evgeniy Dushistov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ufs/balloc.c | 5 ++++- fs/ufs/inode.c | 14 +++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) (limited to 'fs/ufs') diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index 2e0021e8f36..96ca8453bab 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c @@ -233,7 +233,7 @@ static void ufs_change_blocknr(struct inode *inode, unsigned int baseblk, { unsigned int blk_per_page = 1 << (PAGE_CACHE_SHIFT - inode->i_blkbits); struct address_space *mapping = inode->i_mapping; - pgoff_t index, cur_index = locked_page->index; + pgoff_t index, cur_index; unsigned int i, j; struct page *page; struct buffer_head *head, *bh; @@ -241,8 +241,11 @@ static void ufs_change_blocknr(struct inode *inode, unsigned int baseblk, UFSD("ENTER, ino %lu, count %u, oldb %u, newb %u\n", inode->i_ino, count, oldb, newb); + BUG_ON(!locked_page); BUG_ON(!PageLocked(locked_page)); + cur_index = locked_page->index; + for (i = 0; i < count; i += blk_per_page) { index = (baseblk+i) >> (PAGE_CACHE_SHIFT - inode->i_blkbits); diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 2fbab0aab68..4295ca91cf8 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -242,7 +242,8 @@ repeat: goal = tmp + uspi->s_fpb; tmp = ufs_new_fragments (inode, p, fragment - blockoff, goal, required + blockoff, - err, locked_page); + err, + phys != NULL ? locked_page : NULL); } /* * We will extend last allocated block @@ -250,7 +251,7 @@ repeat: else if (lastblock == block) { tmp = ufs_new_fragments(inode, p, fragment - (blockoff - lastblockoff), fs32_to_cpu(sb, *p), required + (blockoff - lastblockoff), - err, locked_page); + err, phys != NULL ? locked_page : NULL); } else /* (lastblock > block) */ { /* * We will allocate new block before last allocated block @@ -261,7 +262,8 @@ repeat: goal = tmp + uspi->s_fpb; } tmp = ufs_new_fragments(inode, p, fragment - blockoff, - goal, uspi->s_fpb, err, locked_page); + goal, uspi->s_fpb, err, + phys != NULL ? locked_page : NULL); } if (!tmp) { if ((!blockoff && *p) || @@ -438,9 +440,11 @@ int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buffer_head * it much more readable: */ #define GET_INODE_DATABLOCK(x) \ - ufs_inode_getfrag(inode, x, fragment, 1, &err, &phys, &new, bh_result->b_page) + ufs_inode_getfrag(inode, x, fragment, 1, &err, &phys, &new,\ + bh_result->b_page) #define GET_INODE_PTR(x) \ - ufs_inode_getfrag(inode, x, fragment, uspi->s_fpb, &err, NULL, NULL, NULL) + ufs_inode_getfrag(inode, x, fragment, uspi->s_fpb, &err, NULL, NULL,\ + bh_result->b_page) #define GET_INDIRECT_DATABLOCK(x) \ ufs_inode_getblock(inode, bh, x, fragment, \ &err, &phys, &new, bh_result->b_page) -- cgit v1.2.3-70-g09d2