diff options
author | Mingming Cao <cmm@us.ibm.com> | 2008-02-25 15:29:55 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2008-02-25 15:29:55 -0500 |
commit | f5ab0d1f8f7df937778c60c3da6f4ef939a54a7b (patch) | |
tree | 9a5b63d45dc805383f7789bba75f7935626767fe /fs/ext4/extents.c | |
parent | 825f1481ead4ce40671089bae7412ac3519e8caa (diff) |
ext4: Fix BUG when writing to an unitialized extent
This patch fixes a bug when writing to preallocated but uninitialized
blocks, which resulted in a BUG in fs/buffer.c saying that the buffer
is not mapped.
When writing to a file, ext4_get_block_wrap() is called with create=1 in
order to request that blocks be allocated if necessary. It currently
calls ext4_get_blocks() with create=0 in order to do a lookup first. If
the inode contains an unitialized data block, the buffer head is left
unampped, which ext4_get_blocks_wrap() returns, causing the BUG.
We fix this by checking to see if the buffer head is unmapped, and if
so, we make sure the the buffer head is mapped by calling
ext4_ext_get_blocks with create=1.
Signed-off-by: Mingming Cao <cmm@us.ibm.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/extents.c')
-rw-r--r-- | fs/ext4/extents.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 8a59f7ba30e..bcf5d040e32 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -2287,9 +2287,22 @@ out: } /* + * Block allocation/map/preallocation routine for extents based files + * + * * Need to be called with * down_read(&EXT4_I(inode)->i_data_sem) if not allocating file system block * (ie, create is zero). Otherwise down_write(&EXT4_I(inode)->i_data_sem) + * + * return > 0, number of of blocks already mapped/allocated + * if create == 0 and these are pre-allocated blocks + * buffer head is unmapped + * otherwise blocks are mapped + * + * return = 0, if plain look up failed (blocks have not been allocated) + * buffer head is unmapped + * + * return < 0, error case. */ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, ext4_lblk_t iblock, |