Commit 4b25a37e authored by Evgeniy Dushistov's avatar Evgeniy Dushistov Committed by Linus Torvalds

[PATCH] ufs: zeroize the rest of block in truncate

This patch fix behaviour in such test scenario:

  lseek(fd, BIG_OFFSET)
  write(fd, buf, sizeof(buf))
  truncate(BIG_OFFSET)
  truncate(BIG_OFFSET + sizeof(buf))
  read(fd, buf...)

Because of if file big enough(BIG_OFFSET) we start allocate space by block,
ordinary block size > page size, so we should zeroize the rest of block in
truncate(except last framgnet, about which VFS should care), to not get
garbage, when we extend file.

Also patch corrects conversion from pointer to block to physical block number,
this helps in case of not common used UFS types.

And add to debug output inode number.
Signed-off-by: default avatarEvgeniy Dushistov <dushistov@mail.ru>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 5431bf97
...@@ -482,8 +482,9 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment, ...@@ -482,8 +482,9 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
if (result) { if (result) {
ufs_clear_frags(inode, result + oldcount, newcount - oldcount, ufs_clear_frags(inode, result + oldcount, newcount - oldcount,
locked_page != NULL); locked_page != NULL);
ufs_change_blocknr(inode, fragment - oldcount, oldcount, tmp, ufs_change_blocknr(inode, fragment - oldcount, oldcount,
result, locked_page); uspi->s_sbbase + tmp,
uspi->s_sbbase + result, locked_page);
ufs_cpu_to_data_ptr(sb, p, result); ufs_cpu_to_data_ptr(sb, p, result);
*err = 0; *err = 0;
UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count); UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count);
......
...@@ -212,7 +212,7 @@ ufs_inode_getfrag(struct inode *inode, u64 fragment, ...@@ -212,7 +212,7 @@ ufs_inode_getfrag(struct inode *inode, u64 fragment,
brelse (result); brelse (result);
goto repeat; goto repeat;
} else { } else {
*phys = tmp + blockoff; *phys = uspi->s_sbbase + tmp + blockoff;
return NULL; return NULL;
} }
} }
...@@ -282,9 +282,9 @@ ufs_inode_getfrag(struct inode *inode, u64 fragment, ...@@ -282,9 +282,9 @@ ufs_inode_getfrag(struct inode *inode, u64 fragment,
} }
if (!phys) { if (!phys) {
result = sb_getblk(sb, tmp + blockoff); result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff);
} else { } else {
*phys = tmp + blockoff; *phys = uspi->s_sbbase + tmp + blockoff;
result = NULL; result = NULL;
*err = 0; *err = 0;
*new = 1; *new = 1;
...@@ -368,7 +368,7 @@ ufs_inode_getblock(struct inode *inode, struct buffer_head *bh, ...@@ -368,7 +368,7 @@ ufs_inode_getblock(struct inode *inode, struct buffer_head *bh,
brelse (result); brelse (result);
goto repeat; goto repeat;
} else { } else {
*phys = tmp + blockoff; *phys = uspi->s_sbbase + tmp + blockoff;
goto out; goto out;
} }
} }
...@@ -389,9 +389,9 @@ ufs_inode_getblock(struct inode *inode, struct buffer_head *bh, ...@@ -389,9 +389,9 @@ ufs_inode_getblock(struct inode *inode, struct buffer_head *bh,
if (!phys) { if (!phys) {
result = sb_getblk(sb, tmp + blockoff); result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff);
} else { } else {
*phys = tmp + blockoff; *phys = uspi->s_sbbase + tmp + blockoff;
*new = 1; *new = 1;
} }
......
...@@ -74,7 +74,7 @@ static int ufs_trunc_direct(struct inode *inode) ...@@ -74,7 +74,7 @@ static int ufs_trunc_direct(struct inode *inode)
unsigned i, tmp; unsigned i, tmp;
int retry; int retry;
UFSD("ENTER\n"); UFSD("ENTER: ino %lu\n", inode->i_ino);
sb = inode->i_sb; sb = inode->i_sb;
uspi = UFS_SB(sb)->s_uspi; uspi = UFS_SB(sb)->s_uspi;
...@@ -96,8 +96,8 @@ static int ufs_trunc_direct(struct inode *inode) ...@@ -96,8 +96,8 @@ static int ufs_trunc_direct(struct inode *inode)
block2 = ufs_fragstoblks (frag3); block2 = ufs_fragstoblks (frag3);
} }
UFSD("frag1 %llu, frag2 %llu, block1 %llu, block2 %llu, frag3 %llu," UFSD("ino %lu, frag1 %llu, frag2 %llu, block1 %llu, block2 %llu,"
" frag4 %llu\n", " frag3 %llu, frag4 %llu\n", inode->i_ino,
(unsigned long long)frag1, (unsigned long long)frag2, (unsigned long long)frag1, (unsigned long long)frag2,
(unsigned long long)block1, (unsigned long long)block2, (unsigned long long)block1, (unsigned long long)block2,
(unsigned long long)frag3, (unsigned long long)frag4); (unsigned long long)frag3, (unsigned long long)frag4);
...@@ -163,7 +163,7 @@ static int ufs_trunc_direct(struct inode *inode) ...@@ -163,7 +163,7 @@ static int ufs_trunc_direct(struct inode *inode)
mark_inode_dirty(inode); mark_inode_dirty(inode);
next3: next3:
UFSD("EXIT\n"); UFSD("EXIT: ino %lu\n", inode->i_ino);
return retry; return retry;
} }
...@@ -248,7 +248,7 @@ static int ufs_trunc_indirect(struct inode *inode, u64 offset, void *p) ...@@ -248,7 +248,7 @@ static int ufs_trunc_indirect(struct inode *inode, u64 offset, void *p)
} }
ubh_brelse (ind_ubh); ubh_brelse (ind_ubh);
UFSD("EXIT\n"); UFSD("EXIT: ino %lu\n", inode->i_ino);
return retry; return retry;
} }
...@@ -262,7 +262,7 @@ static int ufs_trunc_dindirect(struct inode *inode, u64 offset, void *p) ...@@ -262,7 +262,7 @@ static int ufs_trunc_dindirect(struct inode *inode, u64 offset, void *p)
void *dind; void *dind;
int retry = 0; int retry = 0;
UFSD("ENTER\n"); UFSD("ENTER: ino %lu\n", inode->i_ino);
sb = inode->i_sb; sb = inode->i_sb;
uspi = UFS_SB(sb)->s_uspi; uspi = UFS_SB(sb)->s_uspi;
...@@ -312,7 +312,7 @@ static int ufs_trunc_dindirect(struct inode *inode, u64 offset, void *p) ...@@ -312,7 +312,7 @@ static int ufs_trunc_dindirect(struct inode *inode, u64 offset, void *p)
} }
ubh_brelse (dind_bh); ubh_brelse (dind_bh);
UFSD("EXIT\n"); UFSD("EXIT: ino %lu\n", inode->i_ino);
return retry; return retry;
} }
...@@ -327,7 +327,7 @@ static int ufs_trunc_tindirect(struct inode *inode) ...@@ -327,7 +327,7 @@ static int ufs_trunc_tindirect(struct inode *inode)
void *tind, *p; void *tind, *p;
int retry; int retry;
UFSD("ENTER\n"); UFSD("ENTER: ino %lu\n", inode->i_ino);
retry = 0; retry = 0;
...@@ -372,19 +372,21 @@ static int ufs_trunc_tindirect(struct inode *inode) ...@@ -372,19 +372,21 @@ static int ufs_trunc_tindirect(struct inode *inode)
} }
ubh_brelse (tind_bh); ubh_brelse (tind_bh);
UFSD("EXIT\n"); UFSD("EXIT: ino %lu\n", inode->i_ino);
return retry; return retry;
} }
static int ufs_alloc_lastblock(struct inode *inode) static int ufs_alloc_lastblock(struct inode *inode)
{ {
int err = 0; int err = 0;
struct super_block *sb = inode->i_sb;
struct address_space *mapping = inode->i_mapping; struct address_space *mapping = inode->i_mapping;
struct ufs_sb_private_info *uspi = UFS_SB(inode->i_sb)->s_uspi; struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
unsigned i, end; unsigned i, end;
sector_t lastfrag; sector_t lastfrag;
struct page *lastpage; struct page *lastpage;
struct buffer_head *bh; struct buffer_head *bh;
u64 phys64;
lastfrag = (i_size_read(inode) + uspi->s_fsize - 1) >> uspi->s_fshift; lastfrag = (i_size_read(inode) + uspi->s_fsize - 1) >> uspi->s_fshift;
...@@ -424,6 +426,20 @@ static int ufs_alloc_lastblock(struct inode *inode) ...@@ -424,6 +426,20 @@ static int ufs_alloc_lastblock(struct inode *inode)
set_page_dirty(lastpage); set_page_dirty(lastpage);
} }
if (lastfrag >= UFS_IND_FRAGMENT) {
end = uspi->s_fpb - ufs_fragnum(lastfrag) - 1;
phys64 = bh->b_blocknr + 1;
for (i = 0; i < end; ++i) {
bh = sb_getblk(sb, i + phys64);
lock_buffer(bh);
memset(bh->b_data, 0, sb->s_blocksize);
set_buffer_uptodate(bh);
mark_buffer_dirty(bh);
unlock_buffer(bh);
sync_dirty_buffer(bh);
brelse(bh);
}
}
out_unlock: out_unlock:
ufs_put_locked_page(lastpage); ufs_put_locked_page(lastpage);
out: out:
......
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