Commit a685e26f authored by Evgeniy Dushistov's avatar Evgeniy Dushistov Committed by Linus Torvalds

[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: default avatarEvgeniy Dushistov <dushistov@mail.ru>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent ff795447
...@@ -233,7 +233,7 @@ static void ufs_change_blocknr(struct inode *inode, unsigned int baseblk, ...@@ -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); unsigned int blk_per_page = 1 << (PAGE_CACHE_SHIFT - inode->i_blkbits);
struct address_space *mapping = inode->i_mapping; struct address_space *mapping = inode->i_mapping;
pgoff_t index, cur_index = locked_page->index; pgoff_t index, cur_index;
unsigned int i, j; unsigned int i, j;
struct page *page; struct page *page;
struct buffer_head *head, *bh; struct buffer_head *head, *bh;
...@@ -241,8 +241,11 @@ static void ufs_change_blocknr(struct inode *inode, unsigned int baseblk, ...@@ -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", UFSD("ENTER, ino %lu, count %u, oldb %u, newb %u\n",
inode->i_ino, count, oldb, newb); inode->i_ino, count, oldb, newb);
BUG_ON(!locked_page);
BUG_ON(!PageLocked(locked_page)); BUG_ON(!PageLocked(locked_page));
cur_index = locked_page->index;
for (i = 0; i < count; i += blk_per_page) { for (i = 0; i < count; i += blk_per_page) {
index = (baseblk+i) >> (PAGE_CACHE_SHIFT - inode->i_blkbits); index = (baseblk+i) >> (PAGE_CACHE_SHIFT - inode->i_blkbits);
......
...@@ -242,7 +242,8 @@ ufs_inode_getfrag(struct inode *inode, unsigned int fragment, ...@@ -242,7 +242,8 @@ ufs_inode_getfrag(struct inode *inode, unsigned int fragment,
goal = tmp + uspi->s_fpb; goal = tmp + uspi->s_fpb;
tmp = ufs_new_fragments (inode, p, fragment - blockoff, tmp = ufs_new_fragments (inode, p, fragment - blockoff,
goal, required + blockoff, goal, required + blockoff,
err, locked_page); err,
phys != NULL ? locked_page : NULL);
} }
/* /*
* We will extend last allocated block * We will extend last allocated block
...@@ -250,7 +251,7 @@ ufs_inode_getfrag(struct inode *inode, unsigned int fragment, ...@@ -250,7 +251,7 @@ ufs_inode_getfrag(struct inode *inode, unsigned int fragment,
else if (lastblock == block) { else if (lastblock == block) {
tmp = ufs_new_fragments(inode, p, fragment - (blockoff - lastblockoff), tmp = ufs_new_fragments(inode, p, fragment - (blockoff - lastblockoff),
fs32_to_cpu(sb, *p), required + (blockoff - lastblockoff), fs32_to_cpu(sb, *p), required + (blockoff - lastblockoff),
err, locked_page); err, phys != NULL ? locked_page : NULL);
} else /* (lastblock > block) */ { } else /* (lastblock > block) */ {
/* /*
* We will allocate new block before last allocated block * We will allocate new block before last allocated block
...@@ -261,7 +262,8 @@ ufs_inode_getfrag(struct inode *inode, unsigned int fragment, ...@@ -261,7 +262,8 @@ ufs_inode_getfrag(struct inode *inode, unsigned int fragment,
goal = tmp + uspi->s_fpb; goal = tmp + uspi->s_fpb;
} }
tmp = ufs_new_fragments(inode, p, fragment - blockoff, 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 (!tmp) {
if ((!blockoff && *p) || if ((!blockoff && *p) ||
...@@ -438,9 +440,11 @@ int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buffer_head ...@@ -438,9 +440,11 @@ int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buffer_head
* it much more readable: * it much more readable:
*/ */
#define GET_INODE_DATABLOCK(x) \ #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) \ #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) \ #define GET_INDIRECT_DATABLOCK(x) \
ufs_inode_getblock(inode, bh, x, fragment, \ ufs_inode_getblock(inode, bh, x, fragment, \
&err, &phys, &new, bh_result->b_page) &err, &phys, &new, bh_result->b_page)
......
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