--- /dev/null
+Index: linux-stage/fs/ext4/ext4_extents.h
+===================================================================
+--- linux-stage.orig/fs/ext4/ext4_extents.h
++++ linux-stage/fs/ext4/ext4_extents.h
+@@ -258,7 +258,7 @@ extern int ext4_ext_try_to_merge(struct
+ extern unsigned int ext4_ext_check_overlap(struct inode *, struct ext4_extent *, struct ext4_ext_path *);
+ extern int ext4_ext_insert_extent(handle_t *, struct inode *, struct ext4_ext_path *, struct ext4_extent *, int);
+ extern int ext4_ext_walk_space(struct inode *, ext4_lblk_t, ext4_lblk_t,
+- ext_prepare_callback, void *);
++ ext_prepare_callback, void *, int);
+ extern struct ext4_ext_path *ext4_ext_find_extent(struct inode *, ext4_lblk_t,
+ struct ext4_ext_path *);
+ extern int ext4_ext_search_left(struct inode *, struct ext4_ext_path *,
+Index: linux-stage/fs/ext4/extents.c
+===================================================================
+--- linux-stage.orig/fs/ext4/extents.c
++++ linux-stage/fs/ext4/extents.c
+@@ -1851,7 +1851,7 @@ cleanup:
+
+ int ext4_ext_walk_space(struct inode *inode, ext4_lblk_t block,
+ ext4_lblk_t num, ext_prepare_callback func,
+- void *cbdata)
++ void *cbdata, int locked)
+ {
+ struct ext4_ext_path *path = NULL;
+ struct ext4_ext_cache cbex;
+@@ -1866,9 +1866,11 @@ int ext4_ext_walk_space(struct inode *in
+ while (block < last && block != EXT_MAX_BLOCK) {
+ num = last - block;
+ /* find extent for this block */
+- down_read(&EXT4_I(inode)->i_data_sem);
++ if (!locked)
++ down_read(&EXT4_I(inode)->i_data_sem);
+ path = ext4_ext_find_extent(inode, block, path);
+- up_read(&EXT4_I(inode)->i_data_sem);
++ if (!locked)
++ up_read(&EXT4_I(inode)->i_data_sem);
+ if (IS_ERR(path)) {
+ err = PTR_ERR(path);
+ path = NULL;
+@@ -3987,7 +3989,7 @@ int ext4_fiemap(struct inode *inode, str
+ * ext4_ext_fiemap_cb will push extents back to user.
+ */
+ error = ext4_ext_walk_space(inode, start_blk, len_blks,
+- ext4_ext_fiemap_cb, fieinfo);
++ ext4_ext_fiemap_cb, fieinfo, 0);
+ }
+
+ return error;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17))
# define fsfilt_up_truncate_sem(inode) up(&LDISKFS_I(inode)->truncate_sem);
# define fsfilt_down_truncate_sem(inode) down(&LDISKFS_I(inode)->truncate_sem);
-# define fsfilt_up_truncate_sem_in_cb(inode) do { } while (0)
-# define fsfilt_down_truncate_sem_in_cb(inode) do { } while (0)
#else
# ifdef HAVE_EXT4_LDISKFS
-# ifdef WALK_SPACE_HAS_DATA_SEM /* We only use it in fsfilt_map_nblocks() for now */
-# define fsfilt_up_truncate_sem(inode) do{ }while(0)
-# define fsfilt_down_truncate_sem(inode) do{ }while(0)
-# define fsfilt_up_truncate_sem_in_cb(inode) up_write((&EXT4_I(inode)->i_data_sem))
-# define fsfilt_down_truncate_sem_in_cb(inode) down_write((&EXT4_I(inode)->i_data_sem))
-# else
# define fsfilt_up_truncate_sem(inode) up_write((&LDISKFS_I(inode)->i_data_sem));
# define fsfilt_down_truncate_sem(inode) down_write((&LDISKFS_I(inode)->i_data_sem));
-# define fsfilt_up_truncate_sem_in_cb(inode) do { } while (0)
-# define fsfilt_down_truncate_sem_in_cb(inode) do { } while (0)
-# endif
# else
# define fsfilt_up_truncate_sem(inode) mutex_unlock(&LDISKFS_I(inode)->truncate_mutex);
# define fsfilt_down_truncate_sem(inode) mutex_lock(&LDISKFS_I(inode)->truncate_mutex);
-# define fsfilt_up_truncate_sem_in_cb(inode) do { } while (0)
-# define fsfilt_down_truncate_sem_in_cb(inode) do { } while (0)
# endif
#endif
#define ext3_ext_base inode
#define ext3_ext_base2inode(inode) (inode)
#define EXT_DEPTH(inode) ext_depth(inode)
-#define fsfilt_ext3_ext_walk_space(inode, block, num, cb, cbdata) \
+# if defined(HAVE_EXT4_LDISKFS) && defined(WALK_SPACE_HAS_DATA_SEM)
+/* for kernels 2.6.18-238 and later */
+# define fsfilt_ext3_ext_walk_space(inode, block, num, cb, cbdata, locked) \
+ ext3_ext_walk_space(inode, block, num, cb, cbdata, locked);
+# else
+# define fsfilt_ext3_ext_walk_space(inode, block, num, cb, cbdata, locked) \
ext3_ext_walk_space(inode, block, num, cb, cbdata);
+# endif
#else
#define ext3_ext_base ext3_extents_tree
#define ext3_ext_base2inode(tree) (tree->inode)
-#define fsfilt_ext3_ext_walk_space(tree, block, num, cb, cbdata) \
+#define fsfilt_ext3_ext_walk_space(tree, block, num, cb, cbdata, locked) \
ext3_ext_walk_space(tree, block, num, cb);
#endif
return EXT_REPEAT;
}
- /* In 2.6.32 kernel, ext4_ext_walk_space()'s callback func is not
- * protected by i_data_sem, we need do it ourselves, since we create
- * file system blocks */
- fsfilt_down_truncate_sem_in_cb(inode);
-
count = cex->ec_len;
pblock = new_blocks(handle, base, path, cex->ec_block, &count, &err);
if (!pblock)
BUG_ON(le32_to_cpu(nex.ee_block) != cex->ec_block);
out:
- fsfilt_up_truncate_sem_in_cb(inode);
ext3_journal_stop(handle);
map:
if (err >= 0) {
bp.create = create;
fsfilt_down_truncate_sem(inode);
- err = fsfilt_ext3_ext_walk_space(base, block, num, ext3_ext_new_extent_cb, &bp);
+ err = fsfilt_ext3_ext_walk_space(base, block, num,
+ ext3_ext_new_extent_cb, &bp, 1);
ext3_ext_invalidate_cache(base);
fsfilt_up_truncate_sem(inode);