Skip to content

Commit

Permalink
[PATCH] ufs: zeroize the rest of block in truncate
Browse files Browse the repository at this point in the history
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: Evgeniy Dushistov <dushistov@mail.ru>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Dushistov authored and Linus Torvalds committed Mar 17, 2007
1 parent 5431bf9 commit 4b25a37
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 18 deletions.
5 changes: 3 additions & 2 deletions fs/ufs/balloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -482,8 +482,9 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
if (result) {
ufs_clear_frags(inode, result + oldcount, newcount - oldcount,
locked_page != NULL);
ufs_change_blocknr(inode, fragment - oldcount, oldcount, tmp,
result, locked_page);
ufs_change_blocknr(inode, fragment - oldcount, oldcount,
uspi->s_sbbase + tmp,
uspi->s_sbbase + result, locked_page);
ufs_cpu_to_data_ptr(sb, p, result);
*err = 0;
UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count);
Expand Down
12 changes: 6 additions & 6 deletions fs/ufs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ ufs_inode_getfrag(struct inode *inode, u64 fragment,
brelse (result);
goto repeat;
} else {
*phys = tmp + blockoff;
*phys = uspi->s_sbbase + tmp + blockoff;
return NULL;
}
}
Expand Down Expand Up @@ -282,9 +282,9 @@ ufs_inode_getfrag(struct inode *inode, u64 fragment,
}

if (!phys) {
result = sb_getblk(sb, tmp + blockoff);
result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff);
} else {
*phys = tmp + blockoff;
*phys = uspi->s_sbbase + tmp + blockoff;
result = NULL;
*err = 0;
*new = 1;
Expand Down Expand Up @@ -368,7 +368,7 @@ ufs_inode_getblock(struct inode *inode, struct buffer_head *bh,
brelse (result);
goto repeat;
} else {
*phys = tmp + blockoff;
*phys = uspi->s_sbbase + tmp + blockoff;
goto out;
}
}
Expand All @@ -389,9 +389,9 @@ ufs_inode_getblock(struct inode *inode, struct buffer_head *bh,


if (!phys) {
result = sb_getblk(sb, tmp + blockoff);
result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff);
} else {
*phys = tmp + blockoff;
*phys = uspi->s_sbbase + tmp + blockoff;
*new = 1;
}

Expand Down
36 changes: 26 additions & 10 deletions fs/ufs/truncate.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ static int ufs_trunc_direct(struct inode *inode)
unsigned i, tmp;
int retry;

UFSD("ENTER\n");
UFSD("ENTER: ino %lu\n", inode->i_ino);

sb = inode->i_sb;
uspi = UFS_SB(sb)->s_uspi;
Expand All @@ -96,8 +96,8 @@ static int ufs_trunc_direct(struct inode *inode)
block2 = ufs_fragstoblks (frag3);
}

UFSD("frag1 %llu, frag2 %llu, block1 %llu, block2 %llu, frag3 %llu,"
" frag4 %llu\n",
UFSD("ino %lu, frag1 %llu, frag2 %llu, block1 %llu, block2 %llu,"
" frag3 %llu, frag4 %llu\n", inode->i_ino,
(unsigned long long)frag1, (unsigned long long)frag2,
(unsigned long long)block1, (unsigned long long)block2,
(unsigned long long)frag3, (unsigned long long)frag4);
Expand Down Expand Up @@ -163,7 +163,7 @@ static int ufs_trunc_direct(struct inode *inode)
mark_inode_dirty(inode);
next3:

UFSD("EXIT\n");
UFSD("EXIT: ino %lu\n", inode->i_ino);
return retry;
}

Expand Down Expand Up @@ -248,7 +248,7 @@ static int ufs_trunc_indirect(struct inode *inode, u64 offset, void *p)
}
ubh_brelse (ind_ubh);

UFSD("EXIT\n");
UFSD("EXIT: ino %lu\n", inode->i_ino);

return retry;
}
Expand All @@ -262,7 +262,7 @@ static int ufs_trunc_dindirect(struct inode *inode, u64 offset, void *p)
void *dind;
int retry = 0;

UFSD("ENTER\n");
UFSD("ENTER: ino %lu\n", inode->i_ino);

sb = inode->i_sb;
uspi = UFS_SB(sb)->s_uspi;
Expand Down Expand Up @@ -312,7 +312,7 @@ static int ufs_trunc_dindirect(struct inode *inode, u64 offset, void *p)
}
ubh_brelse (dind_bh);

UFSD("EXIT\n");
UFSD("EXIT: ino %lu\n", inode->i_ino);

return retry;
}
Expand All @@ -327,7 +327,7 @@ static int ufs_trunc_tindirect(struct inode *inode)
void *tind, *p;
int retry;

UFSD("ENTER\n");
UFSD("ENTER: ino %lu\n", inode->i_ino);

retry = 0;

Expand Down Expand Up @@ -372,19 +372,21 @@ static int ufs_trunc_tindirect(struct inode *inode)
}
ubh_brelse (tind_bh);

UFSD("EXIT\n");
UFSD("EXIT: ino %lu\n", inode->i_ino);
return retry;
}

static int ufs_alloc_lastblock(struct inode *inode)
{
int err = 0;
struct super_block *sb = inode->i_sb;
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;
sector_t lastfrag;
struct page *lastpage;
struct buffer_head *bh;
u64 phys64;

lastfrag = (i_size_read(inode) + uspi->s_fsize - 1) >> uspi->s_fshift;

Expand Down Expand Up @@ -424,6 +426,20 @@ static int ufs_alloc_lastblock(struct inode *inode)
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:
ufs_put_locked_page(lastpage);
out:
Expand Down

0 comments on commit 4b25a37

Please sign in to comment.