linux-ext4.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] ext4: cleanup and bugfixes for grow/shrink logic
@ 2011-09-20 14:49 Dmitry Monakhov
  2011-09-20 14:49 ` [PATCH 1/4] ext4: cleanup ext4_ext_grow_indepth code Dmitry Monakhov
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Dmitry Monakhov @ 2011-09-20 14:49 UTC (permalink / raw)
  To: linux-ext4; +Cc: tytso, achender, Dmitry Monakhov

Hi, finally have some time to run some tests on recent kernels.
And it appeared that fallocate interface is buggy
 - fallocate: result in fsck complain due to blocks beyond i_size
   without  EOFBLOCKS_FL
 - punch_hole: also provoke fsck complain and even EIO due to
   incorrect EOFBLOCKS_FL update

#LOG:
#Following two patches are mostly cleanup 
ext4-cleanup-ext4_ext_grow_indepth-code.patch
ext4-move-inode-indepth-shrink-logic-to-didicated-fu.patch
# Later patches are fixes for issues.
ext4-Do-not-clear-EOFBLOCKS_FL-too-soon.patch
ext4-fix-punch_hole-extend-handler.patch
I've also attached my temp testcase for both issues
Will submit generic xfstests based on it soon.

########### TESTCASE###################
#! /bin/bash
#############################################################################
# dmonakhov@openvz.org
# Trivial fsstress test  
# TODO: Add to xfstests
# Required patches
# kill fsstress reliably
#  Message-Id: <1316357699-22692-1-git-send-email-dmonakhov@openvz.org>
# In order unresvsp to work kernel should contain following patch
#  Message-Id: <1316528400-1797-1-git-send-email-dmonakhov@openvz.org>
#############################################################################
# FIXES FOR ext4.git:3.1.0-rc2+
#0001-ext4-cleanup-ext4_ext_grow_indepth-code.patch
#0002-ext4-move-inode-indepth-shrink-logic-to-didicated-fu.patch
#0003-ext4-Do-not-clear-EOFBLOCKS_FL-too-soon.patch
#0004-ext4-fix-punch_hole-extend-handler.patch
#############################################################################
IMG=/dev/sdc
MNT=./mnt
#MNT_EXTRA_OPS="-oloop"
## Create small image
#dd if=/dev/zero of=$IMG bs=1M count=1024000
mkfs.ext4 -F -b4096 $IMG 102400
mkdir -p $MNT
mount -text4 $IMG $MNT $MNT_EXTRA_OPS || exit
## Run stress
~/fsstress -p8 -f fsync=0 -f sync=0 -f fdatasync=0 -f setattr=0  -f unresvsp=2 -d $MNT/TEST -n99999999 &
PID=$!
## dd writers will do write/truncate =>  ENOSPC condition
for ((i=0;i < 10;i++))
do
    dd if=/dev/zero of=$MNT/FILE bs=1M
    sleep 2
done
kill $!
wait $!
umount $MNT
fsck.ext4 -f -n $IMG


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/4] ext4: cleanup ext4_ext_grow_indepth code
  2011-09-20 14:49 [PATCH 0/4] ext4: cleanup and bugfixes for grow/shrink logic Dmitry Monakhov
@ 2011-09-20 14:49 ` Dmitry Monakhov
  2011-09-20 14:49 ` [PATCH 2/4] ext4: move inode indepth shrink logic to didicated function Dmitry Monakhov
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Dmitry Monakhov @ 2011-09-20 14:49 UTC (permalink / raw)
  To: linux-ext4; +Cc: tytso, achender, Dmitry Monakhov

Currently code make an impression what grow procedure is very complicated
and some mythical paths, blocks are involved. But in fact grow in depth
it relatively simple procedure:
 1) Just create new meta block and copy root data to that block.
 2) Convert root from extent to index if old depth == 0
 3) update root block pointer

This patch does:
 - Reorganize code to make it more self explanatory
 - Do not pass path parameter to new_meta_block() in order to
   provoke allocation from inode's group because top-level block
   should site closer to it's inode, but not to leaf data block.

Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
 fs/ext4/extents.c |   41 +++++++++++++++--------------------------
 1 files changed, 15 insertions(+), 26 deletions(-)

diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 0ac5a63..b3a08f0 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -1042,16 +1042,14 @@ cleanup:
  */
 static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
 				 unsigned int flags,
-				 struct ext4_ext_path *path,
 				 struct ext4_extent *newext)
 {
-	struct ext4_ext_path *curp = path;
 	struct ext4_extent_header *neh;
 	struct buffer_head *bh;
 	ext4_fsblk_t newblock;
 	int err = 0;
 
-	newblock = ext4_ext_new_meta_block(handle, inode, path,
+	newblock = ext4_ext_new_meta_block(handle, inode, NULL,
 		newext, &err, flags);
 	if (newblock == 0)
 		return err;
@@ -1071,7 +1069,8 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
 	}
 
 	/* move top-level index/leaf into new block */
-	memmove(bh->b_data, curp->p_hdr, sizeof(EXT4_I(inode)->i_data));
+	memmove(bh->b_data, EXT4_I(inode)->i_data,
+		sizeof(EXT4_I(inode)->i_data));
 
 	/* set size of new block */
 	neh = ext_block_hdr(bh);
@@ -1089,32 +1088,23 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
 	if (err)
 		goto out;
 
-	/* create index in new top-level index: num,max,pointer */
-	err = ext4_ext_get_access(handle, inode, curp);
-	if (err)
-		goto out;
-
-	curp->p_hdr->eh_magic = EXT4_EXT_MAGIC;
-	curp->p_hdr->eh_max = cpu_to_le16(ext4_ext_space_root_idx(inode, 0));
-	curp->p_hdr->eh_entries = cpu_to_le16(1);
-	curp->p_idx = EXT_FIRST_INDEX(curp->p_hdr);
-
-	if (path[0].p_hdr->eh_depth)
-		curp->p_idx->ei_block =
-			EXT_FIRST_INDEX(path[0].p_hdr)->ei_block;
-	else
-		curp->p_idx->ei_block =
-			EXT_FIRST_EXTENT(path[0].p_hdr)->ee_block;
-	ext4_idx_store_pblock(curp->p_idx, newblock);
-
+	/* Update top-level index: num,max,pointer */
 	neh = ext_inode_hdr(inode);
+	neh->eh_entries = cpu_to_le16(1);
+	ext4_idx_store_pblock(EXT_FIRST_INDEX(neh), newblock);
+	if (neh->eh_depth == 0) {
+		/* Root extent block becomes index block */
+		neh->eh_max = cpu_to_le16(ext4_ext_space_root_idx(inode, 0));
+		EXT_FIRST_INDEX(neh)->ei_block =
+			EXT_FIRST_EXTENT(neh)->ee_block;
+	}
 	ext_debug("new root: num %d(%d), lblock %d, ptr %llu\n",
 		  le16_to_cpu(neh->eh_entries), le16_to_cpu(neh->eh_max),
 		  le32_to_cpu(EXT_FIRST_INDEX(neh)->ei_block),
 		  ext4_idx_pblock(EXT_FIRST_INDEX(neh)));
 
-	neh->eh_depth = cpu_to_le16(path->p_depth + 1);
-	err = ext4_ext_dirty(handle, inode, curp);
+	neh->eh_depth = cpu_to_le16(neh->eh_depth + 1);
+	ext4_mark_inode_dirty(handle, inode);
 out:
 	brelse(bh);
 
@@ -1162,8 +1152,7 @@ repeat:
 			err = PTR_ERR(path);
 	} else {
 		/* tree is full, time to grow in depth */
-		err = ext4_ext_grow_indepth(handle, inode, flags,
-					    path, newext);
+		err = ext4_ext_grow_indepth(handle, inode, flags, newext);
 		if (err)
 			goto out;
 
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/4] ext4: move inode indepth shrink logic to didicated function
  2011-09-20 14:49 [PATCH 0/4] ext4: cleanup and bugfixes for grow/shrink logic Dmitry Monakhov
  2011-09-20 14:49 ` [PATCH 1/4] ext4: cleanup ext4_ext_grow_indepth code Dmitry Monakhov
@ 2011-09-20 14:49 ` Dmitry Monakhov
  2011-09-20 14:49 ` [PATCH 3/4] ext4: Do not clear EOFBLOCKS_FL too soon Dmitry Monakhov
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Dmitry Monakhov @ 2011-09-20 14:49 UTC (permalink / raw)
  To: linux-ext4; +Cc: tytso, achender, Dmitry Monakhov

- Add ext4_ext_try_shrink() helper
- ext4_mark_inode_dirty() called externally in order to allow
  caller to butch several inode updates in to one mark_dirty call.

Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
 fs/ext4/extents.c |   62 +++++++++++++++++++++-------------------------------
 1 files changed, 25 insertions(+), 37 deletions(-)

diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index b3a08f0..9032214 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -2497,13 +2497,29 @@ ext4_ext_more_to_rm(struct ext4_ext_path *path)
 	return 1;
 }
 
+static int ext4_ext_try_shrink(handle_t *handle, struct inode *inode)
+{
+	/* TODO: flexible tree reduction should be here */
+	if (ext_depth(inode) && ext_inode_hdr(inode)->eh_entries == 0) {
+		/*
+		 * truncate to zero freed all the tree,
+		 * so we need to correct eh_depth
+		 */
+		ext_inode_hdr(inode)->eh_depth = 0;
+		ext_inode_hdr(inode)->eh_max =
+			cpu_to_le16(ext4_ext_space_root(inode, 0));
+		return 1;
+	}
+	return 0;
+}
+
 static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start)
 {
 	struct super_block *sb = inode->i_sb;
 	int depth = ext_depth(inode);
 	struct ext4_ext_path *path;
 	handle_t *handle;
-	int i, err;
+	int i, err, err2;
 
 	ext_debug("truncate since %u\n", start);
 
@@ -2608,29 +2624,18 @@ again:
 			ext_debug("return to level %d\n", i);
 		}
 	}
-
-	/* TODO: flexible tree reduction should be here */
-	if (path->p_hdr->eh_entries == 0) {
-		/*
-		 * truncate to zero freed all the tree,
-		 * so we need to correct eh_depth
-		 */
-		err = ext4_ext_get_access(handle, inode, path);
-		if (err == 0) {
-			ext_inode_hdr(inode)->eh_depth = 0;
-			ext_inode_hdr(inode)->eh_max =
-				cpu_to_le16(ext4_ext_space_root(inode, 0));
-			err = ext4_ext_dirty(handle, inode, path);
-		}
-	}
+	if(ext4_ext_try_shrink(handle, inode))
+		err2 = ext4_mark_inode_dirty(handle, inode);
+	if (!err)
+		err = err2;
 out:
 	ext4_ext_drop_refs(path);
 	kfree(path);
 	if (err == -EAGAIN)
 		goto again;
-	ext4_journal_stop(handle);
+	err2 = ext4_journal_stop(handle);
 
-	return err;
+	return err ? err : err2;
 }
 
 /*
@@ -3456,28 +3461,11 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 			}
 
 			ext4_ext_mark_uninitialized(ex);
-
 			ext4_ext_invalidate_cache(inode);
-
 			err = ext4_ext_rm_leaf(handle, inode, path,
 				map->m_lblk, map->m_lblk + punched_out);
-
-			if (!err && path->p_hdr->eh_entries == 0) {
-				/*
-				 * Punch hole freed all of this sub tree,
-				 * so we need to correct eh_depth
-				 */
-				err = ext4_ext_get_access(handle, inode, path);
-				if (err == 0) {
-					ext_inode_hdr(inode)->eh_depth = 0;
-					ext_inode_hdr(inode)->eh_max =
-					cpu_to_le16(ext4_ext_space_root(
-						inode, 0));

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/4] ext4: Do not clear EOFBLOCKS_FL too soon
  2011-09-20 14:49 [PATCH 0/4] ext4: cleanup and bugfixes for grow/shrink logic Dmitry Monakhov
  2011-09-20 14:49 ` [PATCH 1/4] ext4: cleanup ext4_ext_grow_indepth code Dmitry Monakhov
  2011-09-20 14:49 ` [PATCH 2/4] ext4: move inode indepth shrink logic to didicated function Dmitry Monakhov
@ 2011-09-20 14:49 ` Dmitry Monakhov
  2011-09-20 14:49 ` [PATCH 4/4] ext4: fix punch_hole extend handler Dmitry Monakhov
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Dmitry Monakhov @ 2011-09-20 14:49 UTC (permalink / raw)
  To: linux-ext4; +Cc: tytso, achender, Dmitry Monakhov

ext4_ext_insert_extent() may fail due to number of reasons (ENOSPC)
so let's update eof flag only after extent was successfully inserted.

Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
 fs/ext4/extents.c |   10 ++++++----
 1 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 9032214..098bf6a 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -3562,10 +3562,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 			map->m_flags |= EXT4_MAP_UNINIT;
 	}
 
-	err = check_eofblocks_fl(handle, inode, map->m_lblk, path, ar.len);
-	if (!err)
-		err = ext4_ext_insert_extent(handle, inode, path,
-					     &newex, flags);
+	err = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
 	if (err) {
 		int fb_flags = flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE ?
 			EXT4_FREE_BLOCKS_NO_QUOT_UPDATE : 0;
@@ -3577,6 +3574,11 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 				 ext4_ext_get_actual_len(&newex), fb_flags);
 		goto out2;
 	}
+	err = check_eofblocks_fl(handle, inode, map->m_lblk, path, ar.len);
+	if (err) {
+		ext4_discard_preallocations(inode);
+		goto out2;
+	}
 
 	/* previous routine could use block we allocated */
 	newblock = ext4_ext_pblock(&newex);
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/4] ext4: fix punch_hole extend handler
  2011-09-20 14:49 [PATCH 0/4] ext4: cleanup and bugfixes for grow/shrink logic Dmitry Monakhov
                   ` (2 preceding siblings ...)
  2011-09-20 14:49 ` [PATCH 3/4] ext4: Do not clear EOFBLOCKS_FL too soon Dmitry Monakhov
@ 2011-09-20 14:49 ` Dmitry Monakhov
  2011-09-20 15:02 ` [PATCH 0/4] ext4: cleanup and bugfixes for grow/shrink logic Dmitry Monakhov
  2011-10-19 11:47 ` [PATCH 0/4] ext4: Ping Dmitry Monakhov
  5 siblings, 0 replies; 7+ messages in thread
From: Dmitry Monakhov @ 2011-09-20 14:49 UTC (permalink / raw)
  To: linux-ext4; +Cc: tytso, achender, Dmitry Monakhov

Current implementation has following issues:
 - EOFBLOCK does not changed if necessery
 - ext4_ext_rm_leaf() may return -EAGAIN due to transaction restart
 - punched extent converted to uninitialized incorrectly
 - fsync() logic is bloken because ei->i_sync_tid was not updated
 - Last but not the least all: punch hole logic is sited directly
   in ext4_ext_map_blocks() on 3rd controll level, IMHO one can
   easily screw-up his eyes while invastigating that code. We have
   nothing to hide aren't we?

This patch performs following changes:
 - Move punch hole logic to didicated function similar to uninitialized
   extent handlers.
 - Clear EOFBLOCK if necessery, unfortunately we can not reuse
   check_eofblock_fl() function because it purpose to handle file
   expansion, but in our case we have to recheck base invariant that:
      clear_eof_flag = (eof_block >= last_allocated_block)
 - Repeat punch hole after transaction restart.
 - Update inode sync transaction id on exit.

Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
 fs/ext4/extents.c |  202 +++++++++++++++++++++++++++++++++-------------------
 1 files changed, 128 insertions(+), 74 deletions(-)

diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 098bf6a..3d17652 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -3285,6 +3285,125 @@ out2:
 	return err ? err : allocated;
 }
 
+static int
+ext4_ext_handle_punched_extent(handle_t *handle, struct inode *inode,
+			struct ext4_map_blocks *map,
+			struct ext4_ext_path *path)
+{
+	struct ext4_extent *ex = path[path->p_depth].p_ext;
+	ext4_lblk_t ee_block =  ext4_ext_get_actual_len(ex);
+	unsigned short ee_len = le32_to_cpu(ex->ee_block);
+	struct ext4_map_blocks punch_map;
+	unsigned int punched_out = 0;
+	int err, inode_dirty = 0;
+
+	/* Punch out the map length, but only to the end of the extent */
+	punched_out = ee_len - (map->m_lblk - ee_block);
+	if (punched_out > map->m_len)
+		punched_out = map->m_len;
+	/*
+	 * Sense extents need to be converted to uninitialized, they must
+	 * fit in an uninitialized extent
+	 */
+	if (punched_out > EXT_UNINIT_MAX_LEN)
+		punched_out = EXT_UNINIT_MAX_LEN;
+
+	punch_map.m_lblk = map->m_lblk;
+	punch_map.m_pblk = map->m_lblk - ee_block + ext4_ext_pblock(ex);;
+	punch_map.m_len = punched_out;
+	punch_map.m_flags = 0;
+
+	/* Check to see if the extent needs to be split */
+	if (punch_map.m_len != ee_len || punch_map.m_lblk != ee_block) {
+		err = ext4_split_extent(handle, inode,	path, &punch_map, 0,
+					EXT4_GET_BLOCKS_PUNCH_OUT_EXT |
+					EXT4_GET_BLOCKS_PRE_IO);
+		if (err < 0) {
+			goto out;
+		}
+		/* find extent for the block at the start of the hole */
+		ext4_ext_drop_refs(path);
+		kfree(path);
+
+		path = ext4_ext_find_extent(inode, map->m_lblk, NULL);
+		if (IS_ERR(path)) {
+			err = PTR_ERR(path);
+			path = NULL;
+			goto out;
+		}
+		ex = path[path->p_depth].p_ext;
+		ee_len = ext4_ext_get_actual_len(ex);
+		ee_block = le32_to_cpu(ex->ee_block);
+	}
+
+	err = ext4_ext_get_access(handle, inode, path + path->p_depth);
+	if (err)
+		return err;
+	ext4_ext_mark_uninitialized(ex);
+	err = ext4_ext_dirty(handle, inode, path + path->p_depth);
+	if (err)
+		goto out;
+	ext4_ext_invalidate_cache(inode);
+	err = ext4_ext_rm_leaf(handle, inode, path, map->m_lblk,
+			map->m_lblk + punched_out);
+	if (err)
+		goto out;
+
+	inode_dirty = ext4_ext_try_shrink(handle, inode);
+	/* We have punched out an extent, if it was the only extent beyond
+	 * i_size  eofblocks flag should be cleared.*/
+	if (ext4_test_inode_flag(inode, EXT4_INODE_EOFBLOCKS)) {
+		ext4_fsblk_t eof_block =
+			(inode->i_size + (1 << inode->i_blkbits) - 1) >>
+				inode->i_blkbits;
+		/* find the latest extent */
+		ext4_ext_drop_refs(path);
+		kfree(path);
+		path = ext4_ext_find_extent(inode, EXT_MAX_BLOCKS -1, NULL);
+		if (IS_ERR(path)) {
+			err = PTR_ERR(path);
+			path = NULL;
+			goto out;
+		}
+		ex = path[path->p_depth].p_ext;
+		if (ex) {
+			ee_len = ext4_ext_get_actual_len(ex);
+			ee_block = le32_to_cpu(ex->ee_block);
+		} else {
+			/* Inode is empty */
+			ee_block = ee_len = 0;
+		}
+		if (eof_block >= ee_block + ee_len) {
+			ext4_clear_inode_flag(inode, EXT4_INODE_EOFBLOCKS);
+			inode_dirty = 1;
+		} else if (!ext4_ext_is_uninitialized(ex)) {
+			EXT4_ERROR_INODE(inode, "initialized extent beyond "
+					"EOF i_size: %lld, ex[%u:%u] "
+					"depth: %d pblock %lld",
+					inode->i_size, ee_block, ee_len,
+					path->p_depth,
+					path[path->p_depth].p_block);
+			err = -EIO;
+			/* Continue, because inode shrink should be
+			 * accomplished regardless to staled eof blocks */
+		}
+	}
+	if (inode_dirty) {
+		int err2 = ext4_mark_inode_dirty(handle, inode);
+		if (!err)
+			err = err2;
+	}
+out:
+	ext4_update_inode_fsync_trans(handle, inode, 0);
+	if (path) {
+		ext4_ext_drop_refs(path);
+		kfree(path);
+	}
+	return err ? err : punched_out;
+}
+
+
+
 /*
  * Block allocation/map/preallocation routine for extents based files
  *
@@ -3306,21 +3425,19 @@ out2:
 int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 			struct ext4_map_blocks *map, int flags)
 {
-	struct ext4_ext_path *path = NULL;
+	struct ext4_ext_path *path;
 	struct ext4_extent newex, *ex;
 	ext4_fsblk_t newblock = 0;
 	int err = 0, depth, ret;
 	unsigned int allocated = 0;
-	unsigned int punched_out = 0;
-	unsigned int result = 0;
 	struct ext4_allocation_request ar;
 	ext4_io_end_t *io = EXT4_I(inode)->cur_aio_dio;
-	struct ext4_map_blocks punch_map;
 
 	ext_debug("blocks %u/%u requested for inode %lu\n",
 		  map->m_lblk, map->m_len, inode->i_ino);
 	trace_ext4_ext_map_blocks_enter(inode, map->m_lblk, map->m_len, flags);
-
+again:
+	path = NULL;
 	/* check in cache */
 	if (!(flags & EXT4_GET_BLOCKS_PUNCH_OUT_EXT) &&
 		ext4_ext_in_cache(inode, map->m_lblk, &newex)) {
@@ -3403,71 +3520,11 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 					allocated, newblock);
 				return ret;
 			}
-
-			/*
-			 * Punch out the map length, but only to the
-			 * end of the extent
-			 */
-			punched_out = allocated < map->m_len ?
-				allocated : map->m_len;
-
-			/*
-			 * Sense extents need to be converted to
-			 * uninitialized, they must fit in an
-			 * uninitialized extent
-			 */
-			if (punched_out > EXT_UNINIT_MAX_LEN)
-				punched_out = EXT_UNINIT_MAX_LEN;
-
-			punch_map.m_lblk = map->m_lblk;
-			punch_map.m_pblk = newblock;
-			punch_map.m_len = punched_out;
-			punch_map.m_flags = 0;
-
-			/* Check to see if the extent needs to be split */
-			if (punch_map.m_len != ee_len ||
-				punch_map.m_lblk != ee_block) {
-
-				ret = ext4_split_extent(handle, inode,
-				path, &punch_map, 0,
-				EXT4_GET_BLOCKS_PUNCH_OUT_EXT |
-				EXT4_GET_BLOCKS_PRE_IO);
-
-				if (ret < 0) {
-					err = ret;
-					goto out2;
-				}
-				/*
-				 * find extent for the block at
-				 * the start of the hole
-				 */
-				ext4_ext_drop_refs(path);
-				kfree(path);
-
-				path = ext4_ext_find_extent(inode,
-				map->m_lblk, NULL);
-				if (IS_ERR(path)) {
-					err = PTR_ERR(path);
-					path = NULL;
-					goto out2;
-				}
-
-				depth = ext_depth(inode);
-				ex = path[depth].p_ext;
-				ee_len = ext4_ext_get_actual_len(ex);
-				ee_block = le32_to_cpu(ex->ee_block);
-				ee_start = ext4_ext_pblock(ex);
-
-			}
-
-			ext4_ext_mark_uninitialized(ex);
-			ext4_ext_invalidate_cache(inode);
-			err = ext4_ext_rm_leaf(handle, inode, path,
-				map->m_lblk, map->m_lblk + punched_out);
-			if (!err && ext4_ext_try_shrink(handle, inode))
-				err = ext4_mark_inode_dirty(handle, inode);
-
-			goto out2;
+			ret = ext4_ext_handle_punched_extent(handle, inode,
+							map, path);
+			if (ret == -EAGAIN)
+				goto again;
+			return ret;
 		}
 	}
 
@@ -3618,10 +3675,7 @@ out2:
 	trace_ext4_ext_map_blocks_exit(inode, map->m_lblk,
 		newblock, map->m_len, err ? err : allocated);
 
-	result = (flags & EXT4_GET_BLOCKS_PUNCH_OUT_EXT) ?
-			punched_out : allocated;

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 0/4] ext4: cleanup and bugfixes for grow/shrink logic
  2011-09-20 14:49 [PATCH 0/4] ext4: cleanup and bugfixes for grow/shrink logic Dmitry Monakhov
                   ` (3 preceding siblings ...)
  2011-09-20 14:49 ` [PATCH 4/4] ext4: fix punch_hole extend handler Dmitry Monakhov
@ 2011-09-20 15:02 ` Dmitry Monakhov
  2011-10-19 11:47 ` [PATCH 0/4] ext4: Ping Dmitry Monakhov
  5 siblings, 0 replies; 7+ messages in thread
From: Dmitry Monakhov @ 2011-09-20 15:02 UTC (permalink / raw)
  To: linux-ext4; +Cc: tytso, achender

On Tue, 20 Sep 2011 18:49:26 +0400, Dmitry Monakhov <dmonakhov@openvz.org> wrote:
> Hi, finally have some time to run some tests on recent kernels.
> # Trivial fsstress test  
BTW current test but with fsstress with ext_ioc_{set/get}_flags support
(Message-Id: <1316357699-22692-2-git-send-email-dmonakhov@openvz.org>)
result in following oops almost immediately.
BUG happens due to delayed block appeared in journal checkpoint list
and was submitted to IO layer. Right i'm working on that issue.
------------[ cut here ]------------
kernel BUG at fs/buffer.c:2917!
invalid opcode: 0000 [#1] SMP 
CPU 1 
Modules linked in: ext4 quota_v2 quota_tree jbd2 iTCO_wdt
iTCO_vendor_support virtio_balloon shpchp virtio_pci virtio_ring virtio
[last unloaded: ext4]

Pid: 15935, comm: fsstress Not tainted 3.1.0-rc2+ #6 Parallels Software
International Inc. Parallels Virtual Platform/Parallels Virtual Platform
RIP: 0010:[<ffffffff81153daa>]  [<ffffffff81153daa>]
submit_bh+0x41/0x10d
RSP: 0018:ffff880009ce5c48  EFLAGS: 00010202
RAX: 000000000004c225 RBX: ffff880027029410 RCX: ffff880009ce5c68
RDX: 0000000000000000 RSI: ffff880027029410 RDI: 0000000000000111
RBP: ffff880009ce5c68 R08: ffff880009ce5ab8 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000111
R13: 000000000000002c R14: ffff88002657a160 R15: ffff880009ce4000
FS:  00007f19f8aa4700(0000) GS:ffff88003c800000(0000)
knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 00007f19f8a82008 CR3: 00000000056d4000 CR4: 00000000000006e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process fsstress (pid: 15935, threadinfo ffff880009ce4000, task
ffff88003ba82360)
Stack:
 ffff880009ce5c68 ffff880027029410 0000000000000111 000000000000002c
 ffff880009ce5c88 ffffffff811563fc ffff88002657a000 ffff880009ce5d44
 ffff880009ce5ce8 ffffffffa002ce0e 0000000091827364 ffff8800129469b0
Call Trace:
 [<ffffffff811563fc>] write_dirty_buffer+0x43/0x48
 [<ffffffffa002ce0e>] __flush_batch+0x3f/0x8a [jbd2]
 [<ffffffffa002d7b8>] jbd2_log_do_checkpoint+0x3ab/0x6ff [jbd2]
 [<ffffffffa00310a6>] jbd2_journal_flush+0x98/0x183 [jbd2]
 [<ffffffffa04811f5>] ext4_change_inode_journal_flag+0x53/0xf0 [ext4]
 [<ffffffffa0485855>] ext4_ioctl+0x309/0x80f [ext4]
 [<ffffffff811308f5>] ? cp_new_stat+0xf7/0x10d
 [<ffffffff8113b93c>] do_vfs_ioctl+0x473/0x4f8
 [<ffffffff8112d669>] ? fcheck_files+0x88/0xe1
 [<ffffffff8113ba17>] sys_ioctl+0x56/0x79
 [<ffffffff81444102>] system_call_fastpath+0x16/0x1b
Code: 89 fc 48 89 f3 a8 04 75 04 0f 0b eb fe 48 8b 06 a8 20 75 04 0f 0b
eb fe 48 83 7e 38 00 75 04 0f 0b eb fe 48 8b 06 f6 c4 02 74 04 <0f> 0b
eb fe 48 8b 06 f6 c4 10 74 04 0f 0b eb fe f0 0f ba 2e 03 
RIP  [<ffffffff81153daa>] submit_bh+0x41/0x10d
 RSP <ffff880009ce5c48>
---[ end trace 3ad6c82780724b7c ]---

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 0/4] ext4: Ping.
  2011-09-20 14:49 [PATCH 0/4] ext4: cleanup and bugfixes for grow/shrink logic Dmitry Monakhov
                   ` (4 preceding siblings ...)
  2011-09-20 15:02 ` [PATCH 0/4] ext4: cleanup and bugfixes for grow/shrink logic Dmitry Monakhov
@ 2011-10-19 11:47 ` Dmitry Monakhov
  5 siblings, 0 replies; 7+ messages in thread
From: Dmitry Monakhov @ 2011-10-19 11:47 UTC (permalink / raw)
  To: linux-ext4; +Cc: tytso, achender

On Tue, 20 Sep 2011 18:49:26 +0400, Dmitry Monakhov <dmonakhov@openvz.org> wrote:
> Hi, finally have some time to run some tests on recent kernels.
> And it appeared that fallocate interface is buggy
>  - fallocate: result in fsck complain due to blocks beyond i_size
>    without  EOFBLOCKS_FL
>  - punch_hole: also provoke fsck complain and even EIO due to
>    incorrect EOFBLOCKS_FL update
> 
Ping.. Tomorrow will be a month since patches was submitted,
Ted, any news, do you have plans to merge it?
PS: testcases was updated and avalable here:
   http://article.gmane.org/gmane.comp.file-systems.ext4/28602
> #LOG:
> #Following two patches are mostly cleanup 
> ext4-cleanup-ext4_ext_grow_indepth-code.patch
> ext4-move-inode-indepth-shrink-logic-to-didicated-fu.patch
> # Later patches are fixes for issues.
> ext4-Do-not-clear-EOFBLOCKS_FL-too-soon.patch
> ext4-fix-punch_hole-extend-handler.patch
> I've also attached my temp testcase for both issues
> Will submit generic xfstests based on it soon.
> 
> ########### TESTCASE###################
> #! /bin/bash
> #############################################################################
> # dmonakhov@openvz.org
> # Trivial fsstress test  
> # TODO: Add to xfstests
> # Required patches
> # kill fsstress reliably
> #  Message-Id: <1316357699-22692-1-git-send-email-dmonakhov@openvz.org>
> # In order unresvsp to work kernel should contain following patch
> #  Message-Id: <1316528400-1797-1-git-send-email-dmonakhov@openvz.org>
> #############################################################################
> # FIXES FOR ext4.git:3.1.0-rc2+
> #0001-ext4-cleanup-ext4_ext_grow_indepth-code.patch
> #0002-ext4-move-inode-indepth-shrink-logic-to-didicated-fu.patch
> #0003-ext4-Do-not-clear-EOFBLOCKS_FL-too-soon.patch
> #0004-ext4-fix-punch_hole-extend-handler.patch
> #############################################################################
> IMG=/dev/sdc
> MNT=./mnt
> #MNT_EXTRA_OPS="-oloop"
> ## Create small image
> #dd if=/dev/zero of=$IMG bs=1M count=1024000
> mkfs.ext4 -F -b4096 $IMG 102400
> mkdir -p $MNT
> mount -text4 $IMG $MNT $MNT_EXTRA_OPS || exit
> ## Run stress
> ~/fsstress -p8 -f fsync=0 -f sync=0 -f fdatasync=0 -f setattr=0  -f unresvsp=2 -d $MNT/TEST -n99999999 &
> PID=$!
> ## dd writers will do write/truncate =>  ENOSPC condition
> for ((i=0;i < 10;i++))
> do
>     dd if=/dev/zero of=$MNT/FILE bs=1M
>     sleep 2
> done
> kill $!
> wait $!
> umount $MNT
> fsck.ext4 -f -n $IMG
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2011-10-19 11:47 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-09-20 14:49 [PATCH 0/4] ext4: cleanup and bugfixes for grow/shrink logic Dmitry Monakhov
2011-09-20 14:49 ` [PATCH 1/4] ext4: cleanup ext4_ext_grow_indepth code Dmitry Monakhov
2011-09-20 14:49 ` [PATCH 2/4] ext4: move inode indepth shrink logic to didicated function Dmitry Monakhov
2011-09-20 14:49 ` [PATCH 3/4] ext4: Do not clear EOFBLOCKS_FL too soon Dmitry Monakhov
2011-09-20 14:49 ` [PATCH 4/4] ext4: fix punch_hole extend handler Dmitry Monakhov
2011-09-20 15:02 ` [PATCH 0/4] ext4: cleanup and bugfixes for grow/shrink logic Dmitry Monakhov
2011-10-19 11:47 ` [PATCH 0/4] ext4: Ping Dmitry Monakhov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).