Commit 022a6dc5 authored by Evgeniy Dushistov's avatar Evgeniy Dushistov Committed by Linus Torvalds

[PATCH] ufs: zero metadata

Presently if we allocate several "metadata" blocks (pointers to indirect
blocks for example), we fill with zeroes only the first block.  This cause
some problems in "truncate" function.  Also this patch remove some unused
arguments from several functions and add comments.
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@osdl.org>
parent 2e006393
...@@ -152,7 +152,7 @@ u64 ufs_frag_map(struct inode *inode, sector_t frag) ...@@ -152,7 +152,7 @@ u64 ufs_frag_map(struct inode *inode, sector_t frag)
return ret; return ret;
} }
static void ufs_clear_block(struct inode *inode, struct buffer_head *bh) static void ufs_clear_frag(struct inode *inode, struct buffer_head *bh)
{ {
lock_buffer(bh); lock_buffer(bh);
memset(bh->b_data, 0, inode->i_sb->s_blocksize); memset(bh->b_data, 0, inode->i_sb->s_blocksize);
...@@ -163,27 +163,52 @@ static void ufs_clear_block(struct inode *inode, struct buffer_head *bh) ...@@ -163,27 +163,52 @@ static void ufs_clear_block(struct inode *inode, struct buffer_head *bh)
sync_dirty_buffer(bh); sync_dirty_buffer(bh);
} }
static struct buffer_head *ufs_inode_getfrag(struct inode *inode, static struct buffer_head *
unsigned int fragment, unsigned int new_fragment, ufs_clear_frags(struct inode *inode, sector_t beg,
unsigned int required, int *err, int metadata, unsigned int n)
{
struct buffer_head *res, *bh;
sector_t end = beg + n;
res = sb_getblk(inode->i_sb, beg);
ufs_clear_frag(inode, res);
for (++beg; beg < end; ++beg) {
bh = sb_getblk(inode->i_sb, beg);
ufs_clear_frag(inode, bh);
}
return res;
}
/**
* ufs_inode_getfrag() - allocate new fragment(s)
* @inode - pointer to inode
* @fragment - number of `fragment' which hold pointer
* to new allocated fragment(s)
* @new_fragment - number of new allocated fragment(s)
* @required - how many fragment(s) we require
* @err - we set it if something wrong
* @phys - pointer to where we save physical number of new allocated fragments,
* NULL if we allocate not data(indirect blocks for example).
* @new - we set it if we allocate new block
* @locked_page - for ufs_new_fragments()
*/
static struct buffer_head *
ufs_inode_getfrag(struct inode *inode, unsigned int fragment,
sector_t new_fragment, unsigned int required, int *err,
long *phys, int *new, struct page *locked_page) long *phys, int *new, struct page *locked_page)
{ {
struct ufs_inode_info *ufsi = UFS_I(inode); struct ufs_inode_info *ufsi = UFS_I(inode);
struct super_block * sb; struct super_block *sb = inode->i_sb;
struct ufs_sb_private_info * uspi; struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
struct buffer_head * result; struct buffer_head * result;
unsigned block, blockoff, lastfrag, lastblock, lastblockoff; unsigned block, blockoff, lastfrag, lastblock, lastblockoff;
unsigned tmp, goal; unsigned tmp, goal;
__fs32 * p, * p2; __fs32 * p, * p2;
unsigned flags = 0;
UFSD("ENTER, ino %lu, fragment %u, new_fragment %u, required %u\n",
inode->i_ino, fragment, new_fragment, required);
sb = inode->i_sb; UFSD("ENTER, ino %lu, fragment %u, new_fragment %llu, required %u, "
uspi = UFS_SB(sb)->s_uspi; "metadata %d\n", inode->i_ino, fragment,
(unsigned long long)new_fragment, required, !phys);
flags = UFS_SB(sb)->s_flags;
/* TODO : to be done for write support /* TODO : to be done for write support
if ( (flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) if ( (flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
goto ufs2; goto ufs2;
...@@ -198,7 +223,7 @@ static struct buffer_head *ufs_inode_getfrag(struct inode *inode, ...@@ -198,7 +223,7 @@ static struct buffer_head *ufs_inode_getfrag(struct inode *inode,
tmp = fs32_to_cpu(sb, *p); tmp = fs32_to_cpu(sb, *p);
lastfrag = ufsi->i_lastfrag; lastfrag = ufsi->i_lastfrag;
if (tmp && fragment < lastfrag) { if (tmp && fragment < lastfrag) {
if (metadata) { if (!phys) {
result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff); result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff);
if (tmp == fs32_to_cpu(sb, *p)) { if (tmp == fs32_to_cpu(sb, *p)) {
UFSD("EXIT, result %u\n", tmp + blockoff); UFSD("EXIT, result %u\n", tmp + blockoff);
...@@ -265,9 +290,8 @@ static struct buffer_head *ufs_inode_getfrag(struct inode *inode, ...@@ -265,9 +290,8 @@ static struct buffer_head *ufs_inode_getfrag(struct inode *inode,
return NULL; return NULL;
} }
if (metadata) { if (!phys) {
result = sb_getblk(inode->i_sb, tmp + blockoff); result = ufs_clear_frags(inode, tmp + blockoff, required);
ufs_clear_block(inode, result);
} else { } else {
*phys = tmp + blockoff; *phys = tmp + blockoff;
result = NULL; result = NULL;
...@@ -298,23 +322,35 @@ static struct buffer_head *ufs_inode_getfrag(struct inode *inode, ...@@ -298,23 +322,35 @@ static struct buffer_head *ufs_inode_getfrag(struct inode *inode,
*/ */
} }
static struct buffer_head *ufs_block_getfrag(struct inode *inode, struct buffer_head *bh, /**
unsigned int fragment, unsigned int new_fragment, * ufs_inode_getblock() - allocate new block
unsigned int blocksize, int * err, int metadata, * @inode - pointer to inode
* @bh - pointer to block which hold "pointer" to new allocated block
* @fragment - number of `fragment' which hold pointer
* to new allocated block
* @new_fragment - number of new allocated fragment
* (block will hold this fragment and also uspi->s_fpb-1)
* @err - see ufs_inode_getfrag()
* @phys - see ufs_inode_getfrag()
* @new - see ufs_inode_getfrag()
* @locked_page - see ufs_inode_getfrag()
*/
static struct buffer_head *
ufs_inode_getblock(struct inode *inode, struct buffer_head *bh,
unsigned int fragment, sector_t new_fragment, int *err,
long *phys, int *new, struct page *locked_page) long *phys, int *new, struct page *locked_page)
{ {
struct super_block * sb; struct super_block *sb = inode->i_sb;
struct ufs_sb_private_info * uspi; struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
struct buffer_head * result; struct buffer_head * result;
unsigned tmp, goal, block, blockoff; unsigned tmp, goal, block, blockoff;
__fs32 * p; __fs32 * p;
sb = inode->i_sb;
uspi = UFS_SB(sb)->s_uspi;
block = ufs_fragstoblks (fragment); block = ufs_fragstoblks (fragment);
blockoff = ufs_fragnum (fragment); blockoff = ufs_fragnum (fragment);
UFSD("ENTER, ino %lu, fragment %u, new_fragment %u\n", inode->i_ino, fragment, new_fragment); UFSD("ENTER, ino %lu, fragment %u, new_fragment %llu, metadata %d\n",
inode->i_ino, fragment, (unsigned long long)new_fragment, !phys);
result = NULL; result = NULL;
if (!bh) if (!bh)
...@@ -330,7 +366,7 @@ static struct buffer_head *ufs_block_getfrag(struct inode *inode, struct buffer_ ...@@ -330,7 +366,7 @@ static struct buffer_head *ufs_block_getfrag(struct inode *inode, struct buffer_
repeat: repeat:
tmp = fs32_to_cpu(sb, *p); tmp = fs32_to_cpu(sb, *p);
if (tmp) { if (tmp) {
if (metadata) { if (!phys) {
result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff); result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff);
if (tmp == fs32_to_cpu(sb, *p)) if (tmp == fs32_to_cpu(sb, *p))
goto out; goto out;
...@@ -355,9 +391,8 @@ static struct buffer_head *ufs_block_getfrag(struct inode *inode, struct buffer_ ...@@ -355,9 +391,8 @@ static struct buffer_head *ufs_block_getfrag(struct inode *inode, struct buffer_
} }
if (metadata) { if (!phys) {
result = sb_getblk(sb, tmp + blockoff); result = ufs_clear_frags(inode, tmp + blockoff, uspi->s_fpb);
ufs_clear_block(inode, result);
} else { } else {
*phys = tmp + blockoff; *phys = tmp + blockoff;
*new = 1; *new = 1;
...@@ -375,11 +410,12 @@ static struct buffer_head *ufs_block_getfrag(struct inode *inode, struct buffer_ ...@@ -375,11 +410,12 @@ static struct buffer_head *ufs_block_getfrag(struct inode *inode, struct buffer_
return result; return result;
} }
/* /**
* This function gets the block which contains the fragment. * ufs_getfrag_bloc() - `get_block_t' function, interface between UFS and
* readpage, writepage and so on
*/ */
int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create) int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create)
{ {
struct super_block * sb = inode->i_sb; struct super_block * sb = inode->i_sb;
struct ufs_sb_private_info * uspi = UFS_SB(sb)->s_uspi; struct ufs_sb_private_info * uspi = UFS_SB(sb)->s_uspi;
...@@ -421,15 +457,15 @@ int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_hea ...@@ -421,15 +457,15 @@ int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_hea
* 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, 0, &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, 1, NULL, NULL, bh_result->b_page) 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_block_getfrag(inode, bh, x, fragment, sb->s_blocksize, \ ufs_inode_getblock(inode, bh, x, fragment, \
&err, 0, &phys, &new, bh_result->b_page); &err, &phys, &new, bh_result->b_page);
#define GET_INDIRECT_PTR(x) \ #define GET_INDIRECT_PTR(x) \
ufs_block_getfrag(inode, bh, x, fragment, sb->s_blocksize, \ ufs_inode_getblock(inode, bh, x, fragment, \
&err, 1, NULL, NULL, bh_result->b_page); &err, NULL, NULL, bh_result->b_page);
if (ptr < UFS_NDIR_FRAGMENT) { if (ptr < UFS_NDIR_FRAGMENT) {
bh = GET_INODE_DATABLOCK(ptr); bh = GET_INODE_DATABLOCK(ptr);
......
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