summaryrefslogtreecommitdiffstats
path: root/fs/ext4/ext4_extents.h
diff options
context:
space:
mode:
authorLukas Czerner <lczerner@redhat.com>2012-11-28 12:32:26 -0500
committerTheodore Ts'o <tytso@mit.edu>2012-11-28 12:32:26 -0500
commit91dd8c114499e9818f2d5919ef0b9eee61810220 (patch)
tree5eab15bc469385b207f3e4613cdc47d7078338ca /fs/ext4/ext4_extents.h
parentf3b59291a69d0b734be1fc8be489fef2dd846d3d (diff)
downloadlinux-91dd8c114499e9818f2d5919ef0b9eee61810220.tar.gz
linux-91dd8c114499e9818f2d5919ef0b9eee61810220.tar.bz2
linux-91dd8c114499e9818f2d5919ef0b9eee61810220.zip
ext4: prevent race while walking extent tree for fiemap
Currently ext4_ext_walk_space() only takes i_data_sem for read when searching for the extent at given block with ext4_ext_find_extent(). Then it drops the lock and the extent tree can be changed at will. However later on we're searching for the 'next' extent, but the extent tree might already have changed, so the information might not be accurate. In fact we can hit BUG_ON(end <= start) if the extent got inserted into the tree after the one we found and before the block we were searching for. This has been reproduced by running xfstests 225 in loop on s390x architecture, but theoretically we could hit this on any other architecture as well, but probably not as often. Moreover the extent currently in delayed allocation might be allocated after we search the extent tree and before we search extent status tree delayed buffers resulting in those delayed buffers being completely missed, even though completely written and allocated. We fix all those problems in several steps: 1. remove unnecessary callback indirection 2. rename functions ext4_ext_walk_space -> ext4_fill_fiemap_extents ext4_ext_fiemap_cb -> ext4_find_delayed_extent 3. move fiemap_fill_next_extent() into ext4_fill_fiemap_extents() 4. hold the i_data_sem for: ext4_ext_find_extent() ext4_ext_next_allocated_block() ext4_find_delayed_extent() 5. call fiemap_fill_next_extent after releasing the i_data_sem 6. move path reinitialization into the critical section. Signed-off-by: Lukas Czerner <lczerner@redhat.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/ext4_extents.h')
-rw-r--r--fs/ext4/ext4_extents.h14
1 files changed, 0 insertions, 14 deletions
diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h
index 603bb114735c..173b6c545323 100644
--- a/fs/ext4/ext4_extents.h
+++ b/fs/ext4/ext4_extents.h
@@ -144,20 +144,6 @@ struct ext4_ext_path {
*/
/*
- * to be called by ext4_ext_walk_space()
- * negative retcode - error
- * positive retcode - signal for ext4_ext_walk_space(), see below
- * callback must return valid extent (passed or newly created)
- */
-typedef int (*ext_prepare_callback)(struct inode *, ext4_lblk_t,
- struct ext4_ext_cache *,
- struct ext4_extent *, void *);
-
-#define EXT_CONTINUE 0
-#define EXT_BREAK 1
-#define EXT_REPEAT 2
-
-/*
* Maximum number of logical blocks in a file; ext4_extent's ee_block is
* __le32.
*/