Skip to content

Commit

Permalink
ext4: Cache the correct extent length for uninit extents
Browse files Browse the repository at this point in the history
When we convert an uninitialized extent to an initialized extent
we need to make sure we return the number of blocks in the
extent from the file system block corresponding to logical
file block.  Otherwise we cache wrong extent details and this
results in file system corruption.

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Mingming Cao <cmm@us.ibm.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
  • Loading branch information
Aneesh Kumar K.V authored and Theodore Ts'o committed Apr 30, 2008
1 parent 1a89734 commit 161e7b7
Showing 1 changed file with 43 additions and 5 deletions.
48 changes: 43 additions & 5 deletions fs/ext4/extents.c
Original file line number Diff line number Diff line change
Expand Up @@ -2266,7 +2266,8 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
ex->ee_len = orig_ex.ee_len;
ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
ext4_ext_dirty(handle, inode, path + depth);
return le16_to_cpu(ex->ee_len);
/* zeroed the full extent */
return allocated;
}

/* ex1: ee_block to iblock - 1 : uninitialized */
Expand Down Expand Up @@ -2311,11 +2312,45 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
ex->ee_len = orig_ex.ee_len;
ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
ext4_ext_dirty(handle, inode, path + depth);
return le16_to_cpu(ex->ee_len);
/* zeroed the full extent */
return allocated;

} else if (err)
goto fix_extent_len;

/*
* We need to zero out the second half because
* an fallocate request can update file size and
* converting the second half to initialized extent
* implies that we can leak some junk data to user
* space.
*/
err = ext4_ext_zeroout(inode, ex3);
if (err) {
/*
* We should actually mark the
* second half as uninit and return error
* Insert would have changed the extent
*/
depth = ext_depth(inode);
ext4_ext_drop_refs(path);
path = ext4_ext_find_extent(inode,
iblock, path);
if (IS_ERR(path)) {
err = PTR_ERR(path);
return err;
}
ex = path[depth].p_ext;
err = ext4_ext_get_access(handle, inode,
path + depth);
if (err)
return err;
ext4_ext_mark_uninitialized(ex);
ext4_ext_dirty(handle, inode, path + depth);
return err;
}

/* zeroed the second half */
return allocated;
}
ex3 = &newex;
Expand All @@ -2333,7 +2368,8 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
ex->ee_len = orig_ex.ee_len;
ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
ext4_ext_dirty(handle, inode, path + depth);
return le16_to_cpu(ex->ee_len);
/* zeroed the full extent */
return allocated;

} else if (err)
goto fix_extent_len;
Expand Down Expand Up @@ -2381,7 +2417,8 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
ex->ee_len = orig_ex.ee_len;
ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
ext4_ext_dirty(handle, inode, path + depth);
return le16_to_cpu(ex->ee_len);
/* zero out the first half */
return allocated;
}
}
/*
Expand Down Expand Up @@ -2448,7 +2485,8 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
ex->ee_len = orig_ex.ee_len;
ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
ext4_ext_dirty(handle, inode, path + depth);
return le16_to_cpu(ex->ee_len);
/* zero out the first half */
return allocated;
} else if (err)
goto fix_extent_len;
out:
Expand Down

0 comments on commit 161e7b7

Please sign in to comment.