Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 185852
b: refs/heads/master
c: 1f2acb6
h: refs/heads/master
v: v3
  • Loading branch information
Theodore Ts'o committed Jan 22, 2010
1 parent 198297d commit 0917fb4
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 13 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 15121c18a22ae483279f76dc9e554334b800d0f7
refs/heads/master: 1f2acb6017d8528135ec3b01ab7cd2be6ea0630b
1 change: 1 addition & 0 deletions trunk/fs/ext4/ext4.h
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ struct ext4_new_group_data {
*/
#define EXT4_FREE_BLOCKS_METADATA 0x0001
#define EXT4_FREE_BLOCKS_FORGET 0x0002
#define EXT4_FREE_BLOCKS_VALIDATED 0x0004

/*
* ioctl commands
Expand Down
39 changes: 30 additions & 9 deletions trunk/fs/ext4/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -4130,18 +4130,27 @@ static Indirect *ext4_find_shared(struct inode *inode, int depth,
* We release `count' blocks on disk, but (last - first) may be greater
* than `count' because there can be holes in there.
*/
static void ext4_clear_blocks(handle_t *handle, struct inode *inode,
struct buffer_head *bh,
ext4_fsblk_t block_to_free,
unsigned long count, __le32 *first,
__le32 *last)
static int ext4_clear_blocks(handle_t *handle, struct inode *inode,
struct buffer_head *bh,
ext4_fsblk_t block_to_free,
unsigned long count, __le32 *first,
__le32 *last)
{
__le32 *p;
int flags = EXT4_FREE_BLOCKS_FORGET;
int flags = EXT4_FREE_BLOCKS_FORGET | EXT4_FREE_BLOCKS_VALIDATED;

if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
flags |= EXT4_FREE_BLOCKS_METADATA;

if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), block_to_free,
count)) {
ext4_error(inode->i_sb, __func__, "inode #%lu: "
"attempt to clear blocks %llu len %lu, invalid",
inode->i_ino, (unsigned long long) block_to_free,
count);
return 1;
}

if (try_to_extend_transaction(handle, inode)) {
if (bh) {
BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
Expand All @@ -4160,6 +4169,7 @@ static void ext4_clear_blocks(handle_t *handle, struct inode *inode,
*p = 0;

ext4_free_blocks(handle, inode, 0, block_to_free, count, flags);
return 0;
}

/**
Expand Down Expand Up @@ -4215,9 +4225,10 @@ static void ext4_free_data(handle_t *handle, struct inode *inode,
} else if (nr == block_to_free + count) {
count++;
} else {
ext4_clear_blocks(handle, inode, this_bh,
block_to_free,
count, block_to_free_p, p);
if (ext4_clear_blocks(handle, inode, this_bh,
block_to_free, count,
block_to_free_p, p))
break;
block_to_free = nr;
block_to_free_p = p;
count = 1;
Expand Down Expand Up @@ -4281,6 +4292,16 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode,
if (!nr)
continue; /* A hole */

if (!ext4_data_block_valid(EXT4_SB(inode->i_sb),
nr, 1)) {
ext4_error(inode->i_sb, __func__,
"indirect mapped block in inode "
"#%lu invalid (level %d, blk #%lu)",
inode->i_ino, depth,
(unsigned long) nr);
break;
}

/* Go read the buffer for the next level down */
bh = sb_bread(inode->i_sb, nr);

Expand Down
7 changes: 4 additions & 3 deletions trunk/fs/ext4/mballoc.c
Original file line number Diff line number Diff line change
Expand Up @@ -4476,10 +4476,11 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,

sbi = EXT4_SB(sb);
es = EXT4_SB(sb)->s_es;
if (!ext4_data_block_valid(sbi, block, count)) {
if (!(flags & EXT4_FREE_BLOCKS_VALIDATED) &&
!ext4_data_block_valid(sbi, block, count)) {
ext4_error(sb, __func__,
"Freeing blocks not in datazone - "
"block = %llu, count = %lu", block, count);
"Freeing blocks not in datazone - "
"block = %llu, count = %lu", block, count);
goto error_return;
}

Expand Down

0 comments on commit 0917fb4

Please sign in to comment.