All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 1/3] ext4: refactor code to read the extent tree block
@ 2013-07-11  4:39 Theodore Ts'o
  2013-07-11  4:39 ` [RFC PATCH 2/3] ext4: use unsigned int for es_status values Theodore Ts'o
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Theodore Ts'o @ 2013-07-11  4:39 UTC (permalink / raw)
  To: Ext4 Developers List; +Cc: Zheng Liu, Theodore Ts'o

Refactor out the code needed to read the extent tree block into a
single read_extent_tree_block() function.  In addition to simplifying
the code, it also makes sure that we call the ext4_ext_load_extent
tracepoint whenever we need to read an extent tree block from disk.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
 fs/ext4/extents.c | 100 ++++++++++++++++++++++++------------------------------
 1 file changed, 45 insertions(+), 55 deletions(-)

diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 7097b0f..e174814 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -464,25 +464,41 @@ int ext4_ext_check_inode(struct inode *inode)
 	return ext4_ext_check(inode, ext_inode_hdr(inode), ext_depth(inode));
 }
 
-static int __ext4_ext_check_block(const char *function, unsigned int line,
-				  struct inode *inode,
-				  struct ext4_extent_header *eh,
-				  int depth,
-				  struct buffer_head *bh)
+static struct buffer_head *
+__read_extent_tree_block(const char *function, unsigned int line,
+			 struct inode *inode, ext4_fsblk_t pblk, int depth)
 {
-	int ret;
+	struct buffer_head		*bh;
+	int				err;
+
+	BUG_ON(!rwsem_is_locked(&EXT4_I(inode)->i_data_sem));
+
+	bh = sb_getblk(inode->i_sb, pblk);
+	if (unlikely(!bh))
+		return ERR_PTR(-ENOMEM);
 
+	if (!bh_uptodate_or_lock(bh)) {
+		trace_ext4_ext_load_extent(inode, pblk, _RET_IP_);
+		err = bh_submit_read(bh);
+		if (err < 0)
+			goto errout;
+	}
 	if (buffer_verified(bh))
-		return 0;
-	ret = ext4_ext_check(inode, eh, depth);
-	if (ret)
-		return ret;
+		return bh;
+	err = __ext4_ext_check(function, line, inode,
+			       ext_block_hdr(bh), depth);
+	if (err)
+		goto errout;
 	set_buffer_verified(bh);
-	return ret;
+	return bh;
+errout:
+	put_bh(bh);
+	return ERR_PTR(err);
+
 }
 
-#define ext4_ext_check_block(inode, eh, depth, bh)	\
-	__ext4_ext_check_block(__func__, __LINE__, inode, eh, depth, bh)
+#define read_extent_tree_block(inode, pblk, depth)		\
+	__read_extent_tree_block(__func__, __LINE__, (inode), (pblk), (depth))
 
 #ifdef EXT_DEBUG
 static void ext4_ext_show_path(struct inode *inode, struct ext4_ext_path *path)
@@ -748,20 +764,12 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
 		path[ppos].p_depth = i;
 		path[ppos].p_ext = NULL;
 
-		bh = sb_getblk(inode->i_sb, path[ppos].p_block);
-		if (unlikely(!bh)) {
-			ret = -ENOMEM;
+		bh = read_extent_tree_block(inode, path[ppos].p_block, --i);
+		if (IS_ERR(bh)) {
+			ret = PTR_ERR(bh);
 			goto err;
 		}
-		if (!bh_uptodate_or_lock(bh)) {
-			trace_ext4_ext_load_extent(inode, block,
-						path[ppos].p_block);
-			ret = bh_submit_read(bh);
-			if (ret < 0) {
-				put_bh(bh);
-				goto err;
-			}
-		}
+
 		eh = ext_block_hdr(bh);
 		ppos++;
 		if (unlikely(ppos > depth)) {
@@ -773,11 +781,6 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
 		}
 		path[ppos].p_bh = bh;
 		path[ppos].p_hdr = eh;
-		i--;
-
-		ret = ext4_ext_check_block(inode, eh, i, bh);
-		if (ret < 0)
-			goto err;
 	}
 
 	path[ppos].p_depth = i;
@@ -1412,29 +1415,21 @@ got_index:
 	ix++;
 	block = ext4_idx_pblock(ix);
 	while (++depth < path->p_depth) {
-		bh = sb_bread(inode->i_sb, block);
-		if (bh == NULL)
-			return -EIO;
-		eh = ext_block_hdr(bh);
 		/* subtract from p_depth to get proper eh_depth */
-		if (ext4_ext_check_block(inode, eh,
-					 path->p_depth - depth, bh)) {
-			put_bh(bh);
-			return -EIO;
-		}
+		bh = read_extent_tree_block(inode, *logical,
+					    path->p_depth - depth);
+		if (IS_ERR(bh))
+			return PTR_ERR(bh);
+		eh = ext_block_hdr(bh);
 		ix = EXT_FIRST_INDEX(eh);
 		block = ext4_idx_pblock(ix);
 		put_bh(bh);
 	}
 
-	bh = sb_bread(inode->i_sb, block);
-	if (bh == NULL)
-		return -EIO;
+	bh = read_extent_tree_block(inode, *logical, path->p_depth - depth);
+	if (IS_ERR(bh))
+		return PTR_ERR(bh);
 	eh = ext_block_hdr(bh);
-	if (ext4_ext_check_block(inode, eh, path->p_depth - depth, bh)) {
-		put_bh(bh);
-		return -EIO;
-	}
 	ex = EXT_FIRST_EXTENT(eh);
 found_extent:
 	*logical = le32_to_cpu(ex->ee_block);
@@ -2829,21 +2824,16 @@ again:
 			ext_debug("move to level %d (block %llu)\n",
 				  i + 1, ext4_idx_pblock(path[i].p_idx));
 			memset(path + i + 1, 0, sizeof(*path));
-			bh = sb_bread(sb, ext4_idx_pblock(path[i].p_idx));
-			if (!bh) {
-				/* should we reset i_size? */
-				err = -EIO;
+			bh = read_extent_tree_block(inode,
+				ext4_idx_pblock(path[i].p_idx), depth - i - 1);
+			if (IS_ERR(bh)) {
+				err = PTR_ERR(bh);
 				break;
 			}
 			if (WARN_ON(i + 1 > depth)) {
 				err = -EIO;
 				break;
 			}
-			if (ext4_ext_check_block(inode, ext_block_hdr(bh),
-							depth - i - 1, bh)) {
-				err = -EIO;
-				break;
-			}
 			path[i + 1].p_bh = bh;
 
 			/* save actual number of indexes since this
-- 
1.7.12.rc0.22.gcdd159b


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

* [RFC PATCH 2/3] ext4: use unsigned int for es_status values
  2013-07-11  4:39 [RFC PATCH 1/3] ext4: refactor code to read the extent tree block Theodore Ts'o
@ 2013-07-11  4:39 ` Theodore Ts'o
  2013-07-11 12:48   ` Zheng Liu
  2013-07-11  4:39 ` [RFC PATCH 3/3] ext4: cache all of an extent tree's leaf block upon reading Theodore Ts'o
  2013-07-11 12:41 ` [RFC PATCH 1/3] ext4: refactor code to read the extent tree block Zheng Liu
  2 siblings, 1 reply; 8+ messages in thread
From: Theodore Ts'o @ 2013-07-11  4:39 UTC (permalink / raw)
  To: Ext4 Developers List; +Cc: Zheng Liu, Theodore Ts'o, Zheng Liu

Don't use an unsigned long long for the es_status flags; this requires
that we pass 64-bit values around which is painful on 32-bit systems.
Instead pass the extent status flags around using the low 4 bits of an
unsigned int, and shift them into place when we are reading or writing
es_pblk.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Cc: Zheng Liu <wenqing.lz@taobao.com>
---
 fs/ext4/extents_status.c    |  6 +++---
 fs/ext4/extents_status.h    | 47 ++++++++++++++++++++++++++-------------------
 fs/ext4/inode.c             |  4 ++--
 include/trace/events/ext4.h | 14 +++++++-------
 4 files changed, 39 insertions(+), 32 deletions(-)

diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
index ee018d5..7358fb3 100644
--- a/fs/ext4/extents_status.c
+++ b/fs/ext4/extents_status.c
@@ -261,7 +261,7 @@ void ext4_es_find_delayed_extent_range(struct inode *inode,
 	if (tree->cache_es) {
 		es1 = tree->cache_es;
 		if (in_range(lblk, es1->es_lblk, es1->es_len)) {
-			es_debug("%u cached by [%u/%u) %llu %llx\n",
+			es_debug("%u cached by [%u/%u) %llu %x\n",
 				 lblk, es1->es_lblk, es1->es_len,
 				 ext4_es_pblock(es1), ext4_es_status(es1));
 			goto out;
@@ -641,13 +641,13 @@ out:
  */
 int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
 			  ext4_lblk_t len, ext4_fsblk_t pblk,
-			  unsigned long long status)
+			  unsigned int status)
 {
 	struct extent_status newes;
 	ext4_lblk_t end = lblk + len - 1;
 	int err = 0;
 
-	es_debug("add [%u/%u) %llu %llx to extent status tree of inode %lu\n",
+	es_debug("add [%u/%u) %llu %x to extent status tree of inode %lu\n",
 		 lblk, len, pblk, status, inode->i_ino);
 
 	if (!len)
diff --git a/fs/ext4/extents_status.h b/fs/ext4/extents_status.h
index e936730..ae1be58 100644
--- a/fs/ext4/extents_status.h
+++ b/fs/ext4/extents_status.h
@@ -29,16 +29,26 @@
 /*
  * These flags live in the high bits of extent_status.es_pblk
  */
-#define EXTENT_STATUS_WRITTEN	(1ULL << 63)
-#define EXTENT_STATUS_UNWRITTEN (1ULL << 62)
-#define EXTENT_STATUS_DELAYED	(1ULL << 61)
-#define EXTENT_STATUS_HOLE	(1ULL << 60)
+#define ES_SHIFT	60
+
+#define EXTENT_STATUS_WRITTEN	(1 << 3)
+#define EXTENT_STATUS_UNWRITTEN (1 << 2)
+#define EXTENT_STATUS_DELAYED	(1 << 1)
+#define EXTENT_STATUS_HOLE	(1 << 0)
 
 #define EXTENT_STATUS_FLAGS	(EXTENT_STATUS_WRITTEN | \
 				 EXTENT_STATUS_UNWRITTEN | \
 				 EXTENT_STATUS_DELAYED | \
 				 EXTENT_STATUS_HOLE)
 
+#define ES_WRITTEN		(1ULL << 63)
+#define ES_UNWRITTEN		(1ULL << 62)
+#define ES_DELAYED		(1ULL << 61)
+#define ES_HOLE			(1ULL << 60)
+
+#define ES_MASK			(ES_WRITTEN | ES_UNWRITTEN | \
+				 ES_DELAYED | ES_HOLE)
+
 struct ext4_sb_info;
 struct ext4_extent;
 
@@ -60,7 +70,7 @@ extern void ext4_es_init_tree(struct ext4_es_tree *tree);
 
 extern int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
 				 ext4_lblk_t len, ext4_fsblk_t pblk,
-				 unsigned long long status);
+				 unsigned int status);
 extern int ext4_es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
 				 ext4_lblk_t len);
 extern void ext4_es_find_delayed_extent_range(struct inode *inode,
@@ -72,32 +82,32 @@ extern int ext4_es_zeroout(struct inode *inode, struct ext4_extent *ex);
 
 static inline int ext4_es_is_written(struct extent_status *es)
 {
-	return (es->es_pblk & EXTENT_STATUS_WRITTEN) != 0;
+	return (es->es_pblk & ES_WRITTEN) != 0;
 }
 
 static inline int ext4_es_is_unwritten(struct extent_status *es)
 {
-	return (es->es_pblk & EXTENT_STATUS_UNWRITTEN) != 0;
+	return (es->es_pblk & ES_UNWRITTEN) != 0;
 }
 
 static inline int ext4_es_is_delayed(struct extent_status *es)
 {
-	return (es->es_pblk & EXTENT_STATUS_DELAYED) != 0;
+	return (es->es_pblk & ES_DELAYED) != 0;
 }
 
 static inline int ext4_es_is_hole(struct extent_status *es)
 {
-	return (es->es_pblk & EXTENT_STATUS_HOLE) != 0;
+	return (es->es_pblk & ES_HOLE) != 0;
 }
 
-static inline ext4_fsblk_t ext4_es_status(struct extent_status *es)
+static inline unsigned int ext4_es_status(struct extent_status *es)
 {
-	return (es->es_pblk & EXTENT_STATUS_FLAGS);
+	return (es->es_pblk >> ES_SHIFT);
 }
 
 static inline ext4_fsblk_t ext4_es_pblock(struct extent_status *es)
 {
-	return (es->es_pblk & ~EXTENT_STATUS_FLAGS);
+	return (es->es_pblk & ~ES_MASK);
 }
 
 static inline void ext4_es_store_pblock(struct extent_status *es,
@@ -105,19 +115,16 @@ static inline void ext4_es_store_pblock(struct extent_status *es,
 {
 	ext4_fsblk_t block;
 
-	block = (pb & ~EXTENT_STATUS_FLAGS) |
-		(es->es_pblk & EXTENT_STATUS_FLAGS);
+	block = (pb & ~ES_MASK) | (es->es_pblk & ES_MASK);
 	es->es_pblk = block;
 }
 
 static inline void ext4_es_store_status(struct extent_status *es,
-					unsigned long long status)
+					unsigned int status)
 {
-	ext4_fsblk_t block;
-
-	block = (status & EXTENT_STATUS_FLAGS) |
-		(es->es_pblk & ~EXTENT_STATUS_FLAGS);
-	es->es_pblk = block;
+	es->es_pblk = (((unsigned long long)
+			(status & EXTENT_STATUS_FLAGS) << ES_SHIFT) |
+		       (es->es_pblk & ~ES_MASK));
 }
 
 extern void ext4_es_register_shrinker(struct ext4_sb_info *sbi);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 19a1643..f27fa9d 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -554,7 +554,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
 	}
 	if (retval > 0) {
 		int ret;
-		unsigned long long status;
+		unsigned int status;
 
 #ifdef ES_AGGRESSIVE_TEST
 		if (retval != map->m_len) {
@@ -1638,7 +1638,7 @@ add_delayed:
 		set_buffer_delay(bh);
 	} else if (retval > 0) {
 		int ret;
-		unsigned long long status;
+		unsigned int status;
 
 #ifdef ES_AGGRESSIVE_TEST
 		if (retval != map->m_len) {
diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
index 2068db2..47a355b 100644
--- a/include/trace/events/ext4.h
+++ b/include/trace/events/ext4.h
@@ -64,10 +64,10 @@ struct extent_status;
 	{ EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER,	"LAST_CLUSTER" })
 
 #define show_extent_status(status) __print_flags(status, "",	\
-	{ (1 << 3),	"W" }, 					\
-	{ (1 << 2),	"U" },					\
-	{ (1 << 1),	"D" },					\
-	{ (1 << 0),	"H" })
+	{ EXTENT_STATUS_WRITTEN,	"W" },			\
+	{ EXTENT_STATUS_UNWRITTEN,	"U" },			\
+	{ EXTENT_STATUS_DELAYED,	"D" },			\
+	{ EXTENT_STATUS_HOLE,		"H" })
 
 
 TRACE_EVENT(ext4_free_inode,
@@ -2212,7 +2212,7 @@ TRACE_EVENT(ext4_es_insert_extent,
 		__entry->lblk	= es->es_lblk;
 		__entry->len	= es->es_len;
 		__entry->pblk	= ext4_es_pblock(es);
-		__entry->status	= ext4_es_status(es) >> 60;
+		__entry->status	= ext4_es_status(es);
 	),
 
 	TP_printk("dev %d,%d ino %lu es [%u/%u) mapped %llu status %s",
@@ -2289,7 +2289,7 @@ TRACE_EVENT(ext4_es_find_delayed_extent_range_exit,
 		__entry->lblk	= es->es_lblk;
 		__entry->len	= es->es_len;
 		__entry->pblk	= ext4_es_pblock(es);
-		__entry->status	= ext4_es_status(es) >> 60;
+		__entry->status	= ext4_es_status(es);
 	),
 
 	TP_printk("dev %d,%d ino %lu es [%u/%u) mapped %llu status %s",
@@ -2343,7 +2343,7 @@ TRACE_EVENT(ext4_es_lookup_extent_exit,
 		__entry->lblk	= es->es_lblk;
 		__entry->len	= es->es_len;
 		__entry->pblk	= ext4_es_pblock(es);
-		__entry->status	= ext4_es_status(es) >> 60;
+		__entry->status	= ext4_es_status(es);
 		__entry->found	= found;
 	),
 
-- 
1.7.12.rc0.22.gcdd159b


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

* [RFC PATCH 3/3] ext4: cache all of an extent tree's leaf block upon reading
  2013-07-11  4:39 [RFC PATCH 1/3] ext4: refactor code to read the extent tree block Theodore Ts'o
  2013-07-11  4:39 ` [RFC PATCH 2/3] ext4: use unsigned int for es_status values Theodore Ts'o
@ 2013-07-11  4:39 ` Theodore Ts'o
  2013-07-11 12:52   ` Zheng Liu
  2013-07-11 18:54   ` Zach Brown
  2013-07-11 12:41 ` [RFC PATCH 1/3] ext4: refactor code to read the extent tree block Zheng Liu
  2 siblings, 2 replies; 8+ messages in thread
From: Theodore Ts'o @ 2013-07-11  4:39 UTC (permalink / raw)
  To: Ext4 Developers List; +Cc: Zheng Liu, Theodore Ts'o, Zheng Liu

When we read in an extent tree leaf block from disk, arrange to have
all of its entries cached.  In nearly all cases the in-memory
representation will be more compact than the on-disk representation in
the buffer cache, and it allows us to get the information without
having to traverse the extent tree for successive extents.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Cc: Zheng Liu <wenqing.lz@taobao.com>
---
 fs/ext4/ext4.h              | 14 +++++++-
 fs/ext4/extents.c           | 84 +++++++++++++++++++++++++++++++--------------
 fs/ext4/extents_status.c    | 39 ++++++++++++++++++++-
 fs/ext4/extents_status.h    |  3 ++
 fs/ext4/migrate.c           |  2 +-
 fs/ext4/move_extent.c       |  2 +-
 include/trace/events/ext4.h | 14 +++++++-
 7 files changed, 127 insertions(+), 31 deletions(-)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 6ed348d..a8497b0 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -561,6 +561,17 @@ enum {
 #define EXT4_GET_BLOCKS_NO_PUT_HOLE		0x0200
 
 /*
+ * The bit position of this flag must not overlap with any of the
+ * EXT4_GET_BLOCKS_*.  It is used by ext4_ext_find_extent(),
+ * read_extent_tree_block(), ext4_split_extent_at(),
+ * ext4_ext_insert_extent(), and ext4_ext_create_new_leaf() to
+ * indicate that the we shouldn't be caching the extents when reading
+ * from the extent tree while a truncate or punch hole operation
+ * is in progress.
+ */
+#define EXT4_EX_NOCACHE				0x0400
+
+/*
  * Flags used by ext4_free_blocks
  */
 #define EXT4_FREE_BLOCKS_METADATA	0x0001
@@ -2683,7 +2694,8 @@ extern int ext4_ext_insert_extent(handle_t *, struct inode *,
 				  struct ext4_ext_path *,
 				  struct ext4_extent *, int);
 extern struct ext4_ext_path *ext4_ext_find_extent(struct inode *, ext4_lblk_t,
-						  struct ext4_ext_path *);
+						  struct ext4_ext_path *,
+						  int flags);
 extern void ext4_ext_drop_refs(struct ext4_ext_path *);
 extern int ext4_ext_check_inode(struct inode *inode);
 extern int ext4_find_delalloc_range(struct inode *inode,
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index e174814..506c3fe 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -466,7 +466,8 @@ int ext4_ext_check_inode(struct inode *inode)
 
 static struct buffer_head *
 __read_extent_tree_block(const char *function, unsigned int line,
-			 struct inode *inode, ext4_fsblk_t pblk, int depth)
+			 struct inode *inode, ext4_fsblk_t pblk, int depth,
+			 int flags)
 {
 	struct buffer_head		*bh;
 	int				err;
@@ -490,6 +491,31 @@ __read_extent_tree_block(const char *function, unsigned int line,
 	if (err)
 		goto errout;
 	set_buffer_verified(bh);
+	/*
+	 * If this is a leaf block, cache all of its entries
+	 */
+	if (!(flags & EXT4_EX_NOCACHE) && depth == 0) {
+		struct ext4_extent_header *eh = ext_block_hdr(bh);
+		struct ext4_extent *ex = EXT_FIRST_EXTENT(eh);
+		int i;
+
+		for (i = eh->eh_entries; i > 0; i--, ex++) {
+			unsigned int status = EXTENT_STATUS_WRITTEN;
+			ext4_lblk_t prev = 0, lblk = le32_to_cpu(ex->ee_block);
+			int len = ext4_ext_get_actual_len(ex);
+
+			if (prev && (prev != lblk))
+				ext4_es_cache_extent(inode, prev,
+						     lblk - prev, ~0,
+						     EXTENT_STATUS_HOLE);
+
+			if (ext4_ext_is_uninitialized(ex))
+				status = EXTENT_STATUS_UNWRITTEN;
+			ext4_es_cache_extent(inode, lblk, len,
+					     ext4_ext_pblock(ex), status);
+			prev = lblk + len;
+		}
+	}
 	return bh;
 errout:
 	put_bh(bh);
@@ -497,8 +523,9 @@ errout:
 
 }
 
-#define read_extent_tree_block(inode, pblk, depth)		\
-	__read_extent_tree_block(__func__, __LINE__, (inode), (pblk), (depth))
+#define read_extent_tree_block(inode, pblk, depth, flags)		\
+	__read_extent_tree_block(__func__, __LINE__, (inode), (pblk),   \
+				 (depth), (flags))
 
 #ifdef EXT_DEBUG
 static void ext4_ext_show_path(struct inode *inode, struct ext4_ext_path *path)
@@ -732,7 +759,7 @@ int ext4_ext_tree_init(handle_t *handle, struct inode *inode)
 
 struct ext4_ext_path *
 ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
-					struct ext4_ext_path *path)
+		     struct ext4_ext_path *path, int flags)
 {
 	struct ext4_extent_header *eh;
 	struct buffer_head *bh;
@@ -764,7 +791,8 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
 		path[ppos].p_depth = i;
 		path[ppos].p_ext = NULL;
 
-		bh = read_extent_tree_block(inode, path[ppos].p_block, --i);
+		bh = read_extent_tree_block(inode, path[ppos].p_block, --i,
+					    flags);
 		if (IS_ERR(bh)) {
 			ret = PTR_ERR(bh);
 			goto err;
@@ -1201,7 +1229,8 @@ out:
  * if no free index is found, then it requests in-depth growing.
  */
 static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
-				    unsigned int flags,
+				    unsigned int mb_flags,
+				    unsigned int gb_flags,
 				    struct ext4_ext_path *path,
 				    struct ext4_extent *newext)
 {
@@ -1223,7 +1252,7 @@ repeat:
 	if (EXT_HAS_FREE_INDEX(curp)) {
 		/* if we found index with free entry, then use that
 		 * entry: create all needed subtree and add new leaf */
-		err = ext4_ext_split(handle, inode, flags, path, newext, i);
+		err = ext4_ext_split(handle, inode, mb_flags, path, newext, i);
 		if (err)
 			goto out;
 
@@ -1231,12 +1260,12 @@ repeat:
 		ext4_ext_drop_refs(path);
 		path = ext4_ext_find_extent(inode,
 				    (ext4_lblk_t)le32_to_cpu(newext->ee_block),
-				    path);
+				    path, gb_flags);
 		if (IS_ERR(path))
 			err = PTR_ERR(path);
 	} else {
 		/* tree is full, time to grow in depth */
-		err = ext4_ext_grow_indepth(handle, inode, flags, newext);
+		err = ext4_ext_grow_indepth(handle, inode, mb_flags, newext);
 		if (err)
 			goto out;
 
@@ -1244,7 +1273,7 @@ repeat:
 		ext4_ext_drop_refs(path);
 		path = ext4_ext_find_extent(inode,
 				   (ext4_lblk_t)le32_to_cpu(newext->ee_block),
-				    path);
+				    path, gb_flags);
 		if (IS_ERR(path)) {
 			err = PTR_ERR(path);
 			goto out;
@@ -1417,7 +1446,7 @@ got_index:
 	while (++depth < path->p_depth) {
 		/* subtract from p_depth to get proper eh_depth */
 		bh = read_extent_tree_block(inode, *logical,
-					    path->p_depth - depth);
+					    path->p_depth - depth, 0);
 		if (IS_ERR(bh))
 			return PTR_ERR(bh);
 		eh = ext_block_hdr(bh);
@@ -1426,7 +1455,7 @@ got_index:
 		put_bh(bh);
 	}
 
-	bh = read_extent_tree_block(inode, *logical, path->p_depth - depth);
+	bh = read_extent_tree_block(inode, *logical, path->p_depth - depth, 0);
 	if (IS_ERR(bh))
 		return PTR_ERR(bh);
 	eh = ext_block_hdr(bh);
@@ -1788,7 +1817,7 @@ out:
  */
 int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
 				struct ext4_ext_path *path,
-				struct ext4_extent *newext, int flag)
+				struct ext4_extent *newext, int gb_flags)
 {
 	struct ext4_extent_header *eh;
 	struct ext4_extent *ex, *fex;
@@ -1797,7 +1826,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
 	int depth, len, err;
 	ext4_lblk_t next;
 	unsigned uninitialized = 0;
-	int flags = 0;
+	int mb_flags = 0;
 
 	if (unlikely(ext4_ext_get_actual_len(newext) == 0)) {
 		EXT4_ERROR_INODE(inode, "ext4_ext_get_actual_len(newext) == 0");
@@ -1812,7 +1841,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
 	}
 
 	/* try to insert block into found extent and return */
-	if (ex && !(flag & EXT4_GET_BLOCKS_PRE_IO)) {
+	if (ex && !(gb_flags & EXT4_GET_BLOCKS_PRE_IO)) {
 
 		/*
 		 * Try to see whether we should rather test the extent on
@@ -1915,7 +1944,7 @@ prepend:
 	if (next != EXT_MAX_BLOCKS) {
 		ext_debug("next leaf block - %u\n", next);
 		BUG_ON(npath != NULL);
-		npath = ext4_ext_find_extent(inode, next, NULL);
+		npath = ext4_ext_find_extent(inode, next, NULL, 0);
 		if (IS_ERR(npath))
 			return PTR_ERR(npath);
 		BUG_ON(npath->p_depth != path->p_depth);
@@ -1934,9 +1963,10 @@ prepend:
 	 * There is no free space in the found leaf.
 	 * We're gonna add a new leaf in the tree.
 	 */
-	if (flag & EXT4_GET_BLOCKS_METADATA_NOFAIL)
-		flags = EXT4_MB_USE_RESERVED;
-	err = ext4_ext_create_new_leaf(handle, inode, flags, path, newext);
+	if (gb_flags & EXT4_GET_BLOCKS_METADATA_NOFAIL)
+		mb_flags = EXT4_MB_USE_RESERVED;
+	err = ext4_ext_create_new_leaf(handle, inode, mb_flags, gb_flags,
+				       path, newext);
 	if (err)
 		goto cleanup;
 	depth = ext_depth(inode);
@@ -2002,7 +2032,7 @@ has_space:
 
 merge:
 	/* try to merge extents */
-	if (!(flag & EXT4_GET_BLOCKS_PRE_IO))
+	if (!(gb_flags & EXT4_GET_BLOCKS_PRE_IO))
 		ext4_ext_try_to_merge(handle, inode, path, nearex);
 
 
@@ -2045,7 +2075,7 @@ static int ext4_fill_fiemap_extents(struct inode *inode,
 			path = NULL;
 		}
 
-		path = ext4_ext_find_extent(inode, block, path);
+		path = ext4_ext_find_extent(inode, block, path, 0);
 		if (IS_ERR(path)) {
 			up_read(&EXT4_I(inode)->i_data_sem);
 			err = PTR_ERR(path);
@@ -2707,7 +2737,7 @@ again:
 		ext4_lblk_t ee_block;
 
 		/* find extent for this block */
-		path = ext4_ext_find_extent(inode, end, NULL);
+		path = ext4_ext_find_extent(inode, end, NULL, EXT4_EX_NOCACHE);
 		if (IS_ERR(path)) {
 			ext4_journal_stop(handle);
 			return PTR_ERR(path);
@@ -2749,6 +2779,7 @@ again:
 			 */
 			err = ext4_split_extent_at(handle, inode, path,
 					end + 1, split_flag,
+					EXT4_EX_NOCACHE |
 					EXT4_GET_BLOCKS_PRE_IO |
 					EXT4_GET_BLOCKS_METADATA_NOFAIL);
 
@@ -2825,7 +2856,8 @@ again:
 				  i + 1, ext4_idx_pblock(path[i].p_idx));
 			memset(path + i + 1, 0, sizeof(*path));
 			bh = read_extent_tree_block(inode,
-				ext4_idx_pblock(path[i].p_idx), depth - i - 1);
+				ext4_idx_pblock(path[i].p_idx), depth - i - 1,
+				EXT4_EX_NOCACHE);
 			if (IS_ERR(bh)) {
 				err = PTR_ERR(bh);
 				break;
@@ -3168,7 +3200,7 @@ static int ext4_split_extent(handle_t *handle,
 	 * result in split of original leaf or extent zeroout.
 	 */
 	ext4_ext_drop_refs(path);
-	path = ext4_ext_find_extent(inode, map->m_lblk, path);
+	path = ext4_ext_find_extent(inode, map->m_lblk, path, 0);
 	if (IS_ERR(path))
 		return PTR_ERR(path);
 	depth = ext_depth(inode);
@@ -3552,7 +3584,7 @@ static int ext4_convert_unwritten_extents_endio(handle_t *handle,
 		if (err < 0)
 			goto out;
 		ext4_ext_drop_refs(path);
-		path = ext4_ext_find_extent(inode, map->m_lblk, path);
+		path = ext4_ext_find_extent(inode, map->m_lblk, path, 0);
 		if (IS_ERR(path)) {
 			err = PTR_ERR(path);
 			goto out;
@@ -4039,7 +4071,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 	trace_ext4_ext_map_blocks_enter(inode, map->m_lblk, map->m_len, flags);
 
 	/* find extent for this block */
-	path = ext4_ext_find_extent(inode, map->m_lblk, NULL);
+	path = ext4_ext_find_extent(inode, map->m_lblk, NULL, 0);
 	if (IS_ERR(path)) {
 		err = PTR_ERR(path);
 		path = NULL;
diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
index 7358fb3..a84804c 100644
--- a/fs/ext4/extents_status.c
+++ b/fs/ext4/extents_status.c
@@ -417,7 +417,7 @@ static void ext4_es_insert_extent_ext_check(struct inode *inode,
 	unsigned short ee_len;
 	int depth, ee_status, es_status;
 
-	path = ext4_ext_find_extent(inode, es->es_lblk, NULL);
+	path = ext4_ext_find_extent(inode, es->es_lblk, NULL, EXT4_EX_NOCACHE);
 	if (IS_ERR(path))
 		return;
 
@@ -678,6 +678,43 @@ error:
 }
 
 /*
+ * ext4_es_cache_extent() inserts information into the extent status
+ * tree if and only if there isn't information about the range in
+ * question already.
+ */
+void ext4_es_cache_extent(struct inode *inode, ext4_lblk_t lblk,
+			  ext4_lblk_t len, ext4_fsblk_t pblk,
+			  unsigned int status)
+{
+	struct extent_status *es;
+	struct extent_status newes;
+	ext4_lblk_t end = lblk + len - 1;
+
+	es_debug("cache [%u/%u) %llu %x to extent status tree of inode %lu\n",
+		 lblk, len, pblk, status, inode->i_ino);
+	if (!len)
+		return;
+
+	BUG_ON(end < lblk);
+
+	write_lock(&EXT4_I(inode)->i_es_lock);
+
+	es = __es_tree_search(&EXT4_I(inode)->i_es_tree.root, lblk);
+	if (es && ((es->es_lblk <= lblk) || (es->es_lblk <= end)))
+		goto out;
+
+	newes.es_lblk = lblk;
+	newes.es_len = len;
+	ext4_es_store_pblock(&newes, pblk);
+	ext4_es_store_status(&newes, status);
+	trace_ext4_es_cache_extent(inode, &newes);
+
+	__es_insert_extent(inode, &newes);
+out:
+	write_unlock(&EXT4_I(inode)->i_es_lock);
+}
+
+/*
  * ext4_es_lookup_extent() looks up an extent in extent status tree.
  *
  * ext4_es_lookup_extent is called by ext4_map_blocks/ext4_da_map_blocks.
diff --git a/fs/ext4/extents_status.h b/fs/ext4/extents_status.h
index ae1be58..23348d1 100644
--- a/fs/ext4/extents_status.h
+++ b/fs/ext4/extents_status.h
@@ -71,6 +71,9 @@ extern void ext4_es_init_tree(struct ext4_es_tree *tree);
 extern int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
 				 ext4_lblk_t len, ext4_fsblk_t pblk,
 				 unsigned int status);
+extern void ext4_es_cache_extent(struct inode *inode, ext4_lblk_t lblk,
+				 ext4_lblk_t len, ext4_fsblk_t pblk,
+				 unsigned int status);
 extern int ext4_es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
 				 ext4_lblk_t len);
 extern void ext4_es_find_delayed_extent_range(struct inode *inode,
diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
index 49e8bdf..f99bdb8 100644
--- a/fs/ext4/migrate.c
+++ b/fs/ext4/migrate.c
@@ -39,7 +39,7 @@ static int finish_range(handle_t *handle, struct inode *inode,
 	newext.ee_block = cpu_to_le32(lb->first_block);
 	newext.ee_len   = cpu_to_le16(lb->last_block - lb->first_block + 1);
 	ext4_ext_store_pblock(&newext, lb->first_pblock);
-	path = ext4_ext_find_extent(inode, lb->first_block, NULL);
+	path = ext4_ext_find_extent(inode, lb->first_block, NULL, 0);
 
 	if (IS_ERR(path)) {
 		retval = PTR_ERR(path);
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
index e86dddb..7fa4d85 100644
--- a/fs/ext4/move_extent.c
+++ b/fs/ext4/move_extent.c
@@ -37,7 +37,7 @@ get_ext_path(struct inode *inode, ext4_lblk_t lblock,
 	int ret = 0;
 	struct ext4_ext_path *path;
 
-	path = ext4_ext_find_extent(inode, lblock, *orig_path);
+	path = ext4_ext_find_extent(inode, lblock, *orig_path, EXT4_EX_NOCACHE);
 	if (IS_ERR(path))
 		ret = PTR_ERR(path);
 	else if (path[ext_depth(inode)].p_ext == NULL)
diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
index 47a355b..d892b55 100644
--- a/include/trace/events/ext4.h
+++ b/include/trace/events/ext4.h
@@ -2192,7 +2192,7 @@ TRACE_EVENT(ext4_ext_remove_space_done,
 		  (unsigned short) __entry->eh_entries)
 );
 
-TRACE_EVENT(ext4_es_insert_extent,
+DECLARE_EVENT_CLASS(ext4__es_extent,
 	TP_PROTO(struct inode *inode, struct extent_status *es),
 
 	TP_ARGS(inode, es),
@@ -2222,6 +2222,18 @@ TRACE_EVENT(ext4_es_insert_extent,
 		  __entry->pblk, show_extent_status(__entry->status))
 );
 
+DEFINE_EVENT(ext4__es_extent, ext4_es_insert_extent,
+	TP_PROTO(struct inode *inode, struct extent_status *es),
+
+	TP_ARGS(inode, es)
+);
+
+DEFINE_EVENT(ext4__es_extent, ext4_es_cache_extent,
+	TP_PROTO(struct inode *inode, struct extent_status *es),
+
+	TP_ARGS(inode, es)
+);
+
 TRACE_EVENT(ext4_es_remove_extent,
 	TP_PROTO(struct inode *inode, ext4_lblk_t lblk, ext4_lblk_t len),
 
-- 
1.7.12.rc0.22.gcdd159b


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

* Re: [RFC PATCH 1/3] ext4: refactor code to read the extent tree block
  2013-07-11  4:39 [RFC PATCH 1/3] ext4: refactor code to read the extent tree block Theodore Ts'o
  2013-07-11  4:39 ` [RFC PATCH 2/3] ext4: use unsigned int for es_status values Theodore Ts'o
  2013-07-11  4:39 ` [RFC PATCH 3/3] ext4: cache all of an extent tree's leaf block upon reading Theodore Ts'o
@ 2013-07-11 12:41 ` Zheng Liu
  2 siblings, 0 replies; 8+ messages in thread
From: Zheng Liu @ 2013-07-11 12:41 UTC (permalink / raw)
  To: Theodore Ts'o; +Cc: Ext4 Developers List

On Thu, Jul 11, 2013 at 12:39:00AM -0400, Theodore Ts'o wrote:
> Refactor out the code needed to read the extent tree block into a
> single read_extent_tree_block() function.  In addition to simplifying
> the code, it also makes sure that we call the ext4_ext_load_extent
> tracepoint whenever we need to read an extent tree block from disk.
> 
> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>

The patch looks good to me.
Reviewed-by: Zheng Liu <wenqing.lz@taobao.com>

                                                - Zheng

> ---
>  fs/ext4/extents.c | 100 ++++++++++++++++++++++++------------------------------
>  1 file changed, 45 insertions(+), 55 deletions(-)
> 
> diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
> index 7097b0f..e174814 100644
> --- a/fs/ext4/extents.c
> +++ b/fs/ext4/extents.c
> @@ -464,25 +464,41 @@ int ext4_ext_check_inode(struct inode *inode)
>  	return ext4_ext_check(inode, ext_inode_hdr(inode), ext_depth(inode));
>  }
>  
> -static int __ext4_ext_check_block(const char *function, unsigned int line,
> -				  struct inode *inode,
> -				  struct ext4_extent_header *eh,
> -				  int depth,
> -				  struct buffer_head *bh)
> +static struct buffer_head *
> +__read_extent_tree_block(const char *function, unsigned int line,
> +			 struct inode *inode, ext4_fsblk_t pblk, int depth)
>  {
> -	int ret;
> +	struct buffer_head		*bh;
> +	int				err;
> +
> +	BUG_ON(!rwsem_is_locked(&EXT4_I(inode)->i_data_sem));
> +
> +	bh = sb_getblk(inode->i_sb, pblk);
> +	if (unlikely(!bh))
> +		return ERR_PTR(-ENOMEM);
>  
> +	if (!bh_uptodate_or_lock(bh)) {
> +		trace_ext4_ext_load_extent(inode, pblk, _RET_IP_);
> +		err = bh_submit_read(bh);
> +		if (err < 0)
> +			goto errout;
> +	}
>  	if (buffer_verified(bh))
> -		return 0;
> -	ret = ext4_ext_check(inode, eh, depth);
> -	if (ret)
> -		return ret;
> +		return bh;
> +	err = __ext4_ext_check(function, line, inode,
> +			       ext_block_hdr(bh), depth);
> +	if (err)
> +		goto errout;
>  	set_buffer_verified(bh);
> -	return ret;
> +	return bh;
> +errout:
> +	put_bh(bh);
> +	return ERR_PTR(err);
> +
>  }
>  
> -#define ext4_ext_check_block(inode, eh, depth, bh)	\
> -	__ext4_ext_check_block(__func__, __LINE__, inode, eh, depth, bh)
> +#define read_extent_tree_block(inode, pblk, depth)		\
> +	__read_extent_tree_block(__func__, __LINE__, (inode), (pblk), (depth))
>  
>  #ifdef EXT_DEBUG
>  static void ext4_ext_show_path(struct inode *inode, struct ext4_ext_path *path)
> @@ -748,20 +764,12 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
>  		path[ppos].p_depth = i;
>  		path[ppos].p_ext = NULL;
>  
> -		bh = sb_getblk(inode->i_sb, path[ppos].p_block);
> -		if (unlikely(!bh)) {
> -			ret = -ENOMEM;
> +		bh = read_extent_tree_block(inode, path[ppos].p_block, --i);
> +		if (IS_ERR(bh)) {
> +			ret = PTR_ERR(bh);
>  			goto err;
>  		}
> -		if (!bh_uptodate_or_lock(bh)) {
> -			trace_ext4_ext_load_extent(inode, block,
> -						path[ppos].p_block);
> -			ret = bh_submit_read(bh);
> -			if (ret < 0) {
> -				put_bh(bh);
> -				goto err;
> -			}
> -		}
> +
>  		eh = ext_block_hdr(bh);
>  		ppos++;
>  		if (unlikely(ppos > depth)) {
> @@ -773,11 +781,6 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
>  		}
>  		path[ppos].p_bh = bh;
>  		path[ppos].p_hdr = eh;
> -		i--;
> -
> -		ret = ext4_ext_check_block(inode, eh, i, bh);
> -		if (ret < 0)
> -			goto err;
>  	}
>  
>  	path[ppos].p_depth = i;
> @@ -1412,29 +1415,21 @@ got_index:
>  	ix++;
>  	block = ext4_idx_pblock(ix);
>  	while (++depth < path->p_depth) {
> -		bh = sb_bread(inode->i_sb, block);
> -		if (bh == NULL)
> -			return -EIO;
> -		eh = ext_block_hdr(bh);
>  		/* subtract from p_depth to get proper eh_depth */
> -		if (ext4_ext_check_block(inode, eh,
> -					 path->p_depth - depth, bh)) {
> -			put_bh(bh);
> -			return -EIO;
> -		}
> +		bh = read_extent_tree_block(inode, *logical,
> +					    path->p_depth - depth);
> +		if (IS_ERR(bh))
> +			return PTR_ERR(bh);
> +		eh = ext_block_hdr(bh);
>  		ix = EXT_FIRST_INDEX(eh);
>  		block = ext4_idx_pblock(ix);
>  		put_bh(bh);
>  	}
>  
> -	bh = sb_bread(inode->i_sb, block);
> -	if (bh == NULL)
> -		return -EIO;
> +	bh = read_extent_tree_block(inode, *logical, path->p_depth - depth);
> +	if (IS_ERR(bh))
> +		return PTR_ERR(bh);
>  	eh = ext_block_hdr(bh);
> -	if (ext4_ext_check_block(inode, eh, path->p_depth - depth, bh)) {
> -		put_bh(bh);
> -		return -EIO;
> -	}
>  	ex = EXT_FIRST_EXTENT(eh);
>  found_extent:
>  	*logical = le32_to_cpu(ex->ee_block);
> @@ -2829,21 +2824,16 @@ again:
>  			ext_debug("move to level %d (block %llu)\n",
>  				  i + 1, ext4_idx_pblock(path[i].p_idx));
>  			memset(path + i + 1, 0, sizeof(*path));
> -			bh = sb_bread(sb, ext4_idx_pblock(path[i].p_idx));
> -			if (!bh) {
> -				/* should we reset i_size? */
> -				err = -EIO;
> +			bh = read_extent_tree_block(inode,
> +				ext4_idx_pblock(path[i].p_idx), depth - i - 1);
> +			if (IS_ERR(bh)) {
> +				err = PTR_ERR(bh);
>  				break;
>  			}
>  			if (WARN_ON(i + 1 > depth)) {
>  				err = -EIO;
>  				break;
>  			}
> -			if (ext4_ext_check_block(inode, ext_block_hdr(bh),
> -							depth - i - 1, bh)) {
> -				err = -EIO;
> -				break;
> -			}
>  			path[i + 1].p_bh = bh;
>  
>  			/* save actual number of indexes since this
> -- 
> 1.7.12.rc0.22.gcdd159b
> 

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

* Re: [RFC PATCH 2/3] ext4: use unsigned int for es_status values
  2013-07-11  4:39 ` [RFC PATCH 2/3] ext4: use unsigned int for es_status values Theodore Ts'o
@ 2013-07-11 12:48   ` Zheng Liu
  0 siblings, 0 replies; 8+ messages in thread
From: Zheng Liu @ 2013-07-11 12:48 UTC (permalink / raw)
  To: Theodore Ts'o; +Cc: Ext4 Developers List, Zheng Liu

Hi Ted,

On Thu, Jul 11, 2013 at 12:39:01AM -0400, Theodore Ts'o wrote:
> Don't use an unsigned long long for the es_status flags; this requires
> that we pass 64-bit values around which is painful on 32-bit systems.
> Instead pass the extent status flags around using the low 4 bits of an
> unsigned int, and shift them into place when we are reading or writing
> es_pblk.
> 
> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
> Cc: Zheng Liu <wenqing.lz@taobao.com>

Thanks for fixing this.  One minor nit below.  Otherwise, the patch
looks good to me.
Reviewed-by: Zheng Liu <wenqing.lz@taobao.com>

> ---
>  fs/ext4/extents_status.c    |  6 +++---
>  fs/ext4/extents_status.h    | 47 ++++++++++++++++++++++++++-------------------
>  fs/ext4/inode.c             |  4 ++--
>  include/trace/events/ext4.h | 14 +++++++-------
>  4 files changed, 39 insertions(+), 32 deletions(-)
> 
[...]
> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> index 19a1643..f27fa9d 100644
> --- a/fs/ext4/inode.c
> +++ b/fs/ext4/inode.c
> @@ -554,7 +554,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
>  	}
>  	if (retval > 0) {
>  		int ret;
> -		unsigned long long status;
> +		unsigned int status;
>  
>  #ifdef ES_AGGRESSIVE_TEST
>  		if (retval != map->m_len) {

In ext4_map_blocks() function, we have two places that need to be
change.

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index f27fa9d..3cfbcaa 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -655,7 +655,7 @@ found:
 
 	if (retval > 0) {
 		int ret;
-		unsigned long long status;
+		unsigned int status;
 
 #ifdef ES_AGGRESSIVE_TEST
 		if (retval != map->m_len) {

Thanks,
                                                - Zheng

> @@ -1638,7 +1638,7 @@ add_delayed:
>  		set_buffer_delay(bh);
>  	} else if (retval > 0) {
>  		int ret;
> -		unsigned long long status;
> +		unsigned int status;
>  
>  #ifdef ES_AGGRESSIVE_TEST
>  		if (retval != map->m_len) {
> diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
> index 2068db2..47a355b 100644
> --- a/include/trace/events/ext4.h
> +++ b/include/trace/events/ext4.h
> @@ -64,10 +64,10 @@ struct extent_status;
>  	{ EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER,	"LAST_CLUSTER" })
>  
>  #define show_extent_status(status) __print_flags(status, "",	\
> -	{ (1 << 3),	"W" }, 					\
> -	{ (1 << 2),	"U" },					\
> -	{ (1 << 1),	"D" },					\
> -	{ (1 << 0),	"H" })
> +	{ EXTENT_STATUS_WRITTEN,	"W" },			\
> +	{ EXTENT_STATUS_UNWRITTEN,	"U" },			\
> +	{ EXTENT_STATUS_DELAYED,	"D" },			\
> +	{ EXTENT_STATUS_HOLE,		"H" })
>  
>  
>  TRACE_EVENT(ext4_free_inode,
> @@ -2212,7 +2212,7 @@ TRACE_EVENT(ext4_es_insert_extent,
>  		__entry->lblk	= es->es_lblk;
>  		__entry->len	= es->es_len;
>  		__entry->pblk	= ext4_es_pblock(es);
> -		__entry->status	= ext4_es_status(es) >> 60;
> +		__entry->status	= ext4_es_status(es);
>  	),
>  
>  	TP_printk("dev %d,%d ino %lu es [%u/%u) mapped %llu status %s",
> @@ -2289,7 +2289,7 @@ TRACE_EVENT(ext4_es_find_delayed_extent_range_exit,
>  		__entry->lblk	= es->es_lblk;
>  		__entry->len	= es->es_len;
>  		__entry->pblk	= ext4_es_pblock(es);
> -		__entry->status	= ext4_es_status(es) >> 60;
> +		__entry->status	= ext4_es_status(es);
>  	),
>  
>  	TP_printk("dev %d,%d ino %lu es [%u/%u) mapped %llu status %s",
> @@ -2343,7 +2343,7 @@ TRACE_EVENT(ext4_es_lookup_extent_exit,
>  		__entry->lblk	= es->es_lblk;
>  		__entry->len	= es->es_len;
>  		__entry->pblk	= ext4_es_pblock(es);
> -		__entry->status	= ext4_es_status(es) >> 60;
> +		__entry->status	= ext4_es_status(es);
>  		__entry->found	= found;
>  	),
>  
> -- 
> 1.7.12.rc0.22.gcdd159b
> 

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

* Re: [RFC PATCH 3/3] ext4: cache all of an extent tree's leaf block upon reading
  2013-07-11  4:39 ` [RFC PATCH 3/3] ext4: cache all of an extent tree's leaf block upon reading Theodore Ts'o
@ 2013-07-11 12:52   ` Zheng Liu
  2013-07-11 18:54   ` Zach Brown
  1 sibling, 0 replies; 8+ messages in thread
From: Zheng Liu @ 2013-07-11 12:52 UTC (permalink / raw)
  To: Theodore Ts'o; +Cc: Ext4 Developers List, Zheng Liu

On Thu, Jul 11, 2013 at 12:39:02AM -0400, Theodore Ts'o wrote:
> When we read in an extent tree leaf block from disk, arrange to have
> all of its entries cached.  In nearly all cases the in-memory
> representation will be more compact than the on-disk representation in
> the buffer cache, and it allows us to get the information without
> having to traverse the extent tree for successive extents.
> 
> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
> Cc: Zheng Liu <wenqing.lz@taobao.com>

One minor nit below.  Otherwise the patch looks good to me.
Reviewed-by: Zheng Liu <wenqing.lz@taobao.com>

> ---
>  fs/ext4/ext4.h              | 14 +++++++-
>  fs/ext4/extents.c           | 84 +++++++++++++++++++++++++++++++--------------
>  fs/ext4/extents_status.c    | 39 ++++++++++++++++++++-
>  fs/ext4/extents_status.h    |  3 ++
>  fs/ext4/migrate.c           |  2 +-
>  fs/ext4/move_extent.c       |  2 +-
>  include/trace/events/ext4.h | 14 +++++++-
>  7 files changed, 127 insertions(+), 31 deletions(-)
> 
> diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
> index 6ed348d..a8497b0 100644
> --- a/fs/ext4/ext4.h
> +++ b/fs/ext4/ext4.h
> @@ -561,6 +561,17 @@ enum {
>  #define EXT4_GET_BLOCKS_NO_PUT_HOLE		0x0200
>  
>  /*
> + * The bit position of this flag must not overlap with any of the
> + * EXT4_GET_BLOCKS_*.  It is used by ext4_ext_find_extent(),
> + * read_extent_tree_block(), ext4_split_extent_at(),
> + * ext4_ext_insert_extent(), and ext4_ext_create_new_leaf() to
> + * indicate that the we shouldn't be caching the extents when reading
> + * from the extent tree while a truncate or punch hole operation
> + * is in progress.
> + */
> +#define EXT4_EX_NOCACHE				0x0400
> +
> +/*
>   * Flags used by ext4_free_blocks
>   */
>  #define EXT4_FREE_BLOCKS_METADATA	0x0001
> @@ -2683,7 +2694,8 @@ extern int ext4_ext_insert_extent(handle_t *, struct inode *,
>  				  struct ext4_ext_path *,
>  				  struct ext4_extent *, int);
>  extern struct ext4_ext_path *ext4_ext_find_extent(struct inode *, ext4_lblk_t,
> -						  struct ext4_ext_path *);
> +						  struct ext4_ext_path *,
> +						  int flags);
>  extern void ext4_ext_drop_refs(struct ext4_ext_path *);
>  extern int ext4_ext_check_inode(struct inode *inode);
>  extern int ext4_find_delalloc_range(struct inode *inode,
> diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
> index e174814..506c3fe 100644
> --- a/fs/ext4/extents.c
> +++ b/fs/ext4/extents.c
> @@ -466,7 +466,8 @@ int ext4_ext_check_inode(struct inode *inode)
>  
>  static struct buffer_head *
>  __read_extent_tree_block(const char *function, unsigned int line,
> -			 struct inode *inode, ext4_fsblk_t pblk, int depth)
> +			 struct inode *inode, ext4_fsblk_t pblk, int depth,
> +			 int flags)
>  {
>  	struct buffer_head		*bh;
>  	int				err;
> @@ -490,6 +491,31 @@ __read_extent_tree_block(const char *function, unsigned int line,
>  	if (err)
>  		goto errout;
>  	set_buffer_verified(bh);
> +	/*
> +	 * If this is a leaf block, cache all of its entries
> +	 */
> +	if (!(flags & EXT4_EX_NOCACHE) && depth == 0) {
> +		struct ext4_extent_header *eh = ext_block_hdr(bh);
> +		struct ext4_extent *ex = EXT_FIRST_EXTENT(eh);
> +		int i;
> +
> +		for (i = eh->eh_entries; i > 0; i--, ex++) {

Here I get a warning message when I use the following command to build
the ext4 kernel module.

  $ make M=fs/ext4 C=2 CF=-D__CHECK_ENDIAN__
  CHECK   fs/ext4/extents.c
fs/ext4/extents.c:502:24: warning: incorrect type in assignment (different base types)
fs/ext4/extents.c:502:24:    expected int [signed] i
fs/ext4/extents.c:502:24:    got restricted __le16 [usertype] eh_entries

                                                - Zheng

> +			unsigned int status = EXTENT_STATUS_WRITTEN;
> +			ext4_lblk_t prev = 0, lblk = le32_to_cpu(ex->ee_block);
> +			int len = ext4_ext_get_actual_len(ex);
> +
> +			if (prev && (prev != lblk))
> +				ext4_es_cache_extent(inode, prev,
> +						     lblk - prev, ~0,
> +						     EXTENT_STATUS_HOLE);
> +
> +			if (ext4_ext_is_uninitialized(ex))
> +				status = EXTENT_STATUS_UNWRITTEN;
> +			ext4_es_cache_extent(inode, lblk, len,
> +					     ext4_ext_pblock(ex), status);
> +			prev = lblk + len;
> +		}
> +	}
>  	return bh;
>  errout:
>  	put_bh(bh);
> @@ -497,8 +523,9 @@ errout:
>  
>  }
>  
> -#define read_extent_tree_block(inode, pblk, depth)		\
> -	__read_extent_tree_block(__func__, __LINE__, (inode), (pblk), (depth))
> +#define read_extent_tree_block(inode, pblk, depth, flags)		\
> +	__read_extent_tree_block(__func__, __LINE__, (inode), (pblk),   \
> +				 (depth), (flags))
>  
>  #ifdef EXT_DEBUG
>  static void ext4_ext_show_path(struct inode *inode, struct ext4_ext_path *path)
> @@ -732,7 +759,7 @@ int ext4_ext_tree_init(handle_t *handle, struct inode *inode)
>  
>  struct ext4_ext_path *
>  ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
> -					struct ext4_ext_path *path)
> +		     struct ext4_ext_path *path, int flags)
>  {
>  	struct ext4_extent_header *eh;
>  	struct buffer_head *bh;
> @@ -764,7 +791,8 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
>  		path[ppos].p_depth = i;
>  		path[ppos].p_ext = NULL;
>  
> -		bh = read_extent_tree_block(inode, path[ppos].p_block, --i);
> +		bh = read_extent_tree_block(inode, path[ppos].p_block, --i,
> +					    flags);
>  		if (IS_ERR(bh)) {
>  			ret = PTR_ERR(bh);
>  			goto err;
> @@ -1201,7 +1229,8 @@ out:
>   * if no free index is found, then it requests in-depth growing.
>   */
>  static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
> -				    unsigned int flags,
> +				    unsigned int mb_flags,
> +				    unsigned int gb_flags,
>  				    struct ext4_ext_path *path,
>  				    struct ext4_extent *newext)
>  {
> @@ -1223,7 +1252,7 @@ repeat:
>  	if (EXT_HAS_FREE_INDEX(curp)) {
>  		/* if we found index with free entry, then use that
>  		 * entry: create all needed subtree and add new leaf */
> -		err = ext4_ext_split(handle, inode, flags, path, newext, i);
> +		err = ext4_ext_split(handle, inode, mb_flags, path, newext, i);
>  		if (err)
>  			goto out;
>  
> @@ -1231,12 +1260,12 @@ repeat:
>  		ext4_ext_drop_refs(path);
>  		path = ext4_ext_find_extent(inode,
>  				    (ext4_lblk_t)le32_to_cpu(newext->ee_block),
> -				    path);
> +				    path, gb_flags);
>  		if (IS_ERR(path))
>  			err = PTR_ERR(path);
>  	} else {
>  		/* tree is full, time to grow in depth */
> -		err = ext4_ext_grow_indepth(handle, inode, flags, newext);
> +		err = ext4_ext_grow_indepth(handle, inode, mb_flags, newext);
>  		if (err)
>  			goto out;
>  
> @@ -1244,7 +1273,7 @@ repeat:
>  		ext4_ext_drop_refs(path);
>  		path = ext4_ext_find_extent(inode,
>  				   (ext4_lblk_t)le32_to_cpu(newext->ee_block),
> -				    path);
> +				    path, gb_flags);
>  		if (IS_ERR(path)) {
>  			err = PTR_ERR(path);
>  			goto out;
> @@ -1417,7 +1446,7 @@ got_index:
>  	while (++depth < path->p_depth) {
>  		/* subtract from p_depth to get proper eh_depth */
>  		bh = read_extent_tree_block(inode, *logical,
> -					    path->p_depth - depth);
> +					    path->p_depth - depth, 0);
>  		if (IS_ERR(bh))
>  			return PTR_ERR(bh);
>  		eh = ext_block_hdr(bh);
> @@ -1426,7 +1455,7 @@ got_index:
>  		put_bh(bh);
>  	}
>  
> -	bh = read_extent_tree_block(inode, *logical, path->p_depth - depth);
> +	bh = read_extent_tree_block(inode, *logical, path->p_depth - depth, 0);
>  	if (IS_ERR(bh))
>  		return PTR_ERR(bh);
>  	eh = ext_block_hdr(bh);
> @@ -1788,7 +1817,7 @@ out:
>   */
>  int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
>  				struct ext4_ext_path *path,
> -				struct ext4_extent *newext, int flag)
> +				struct ext4_extent *newext, int gb_flags)
>  {
>  	struct ext4_extent_header *eh;
>  	struct ext4_extent *ex, *fex;
> @@ -1797,7 +1826,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
>  	int depth, len, err;
>  	ext4_lblk_t next;
>  	unsigned uninitialized = 0;
> -	int flags = 0;
> +	int mb_flags = 0;
>  
>  	if (unlikely(ext4_ext_get_actual_len(newext) == 0)) {
>  		EXT4_ERROR_INODE(inode, "ext4_ext_get_actual_len(newext) == 0");
> @@ -1812,7 +1841,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
>  	}
>  
>  	/* try to insert block into found extent and return */
> -	if (ex && !(flag & EXT4_GET_BLOCKS_PRE_IO)) {
> +	if (ex && !(gb_flags & EXT4_GET_BLOCKS_PRE_IO)) {
>  
>  		/*
>  		 * Try to see whether we should rather test the extent on
> @@ -1915,7 +1944,7 @@ prepend:
>  	if (next != EXT_MAX_BLOCKS) {
>  		ext_debug("next leaf block - %u\n", next);
>  		BUG_ON(npath != NULL);
> -		npath = ext4_ext_find_extent(inode, next, NULL);
> +		npath = ext4_ext_find_extent(inode, next, NULL, 0);
>  		if (IS_ERR(npath))
>  			return PTR_ERR(npath);
>  		BUG_ON(npath->p_depth != path->p_depth);
> @@ -1934,9 +1963,10 @@ prepend:
>  	 * There is no free space in the found leaf.
>  	 * We're gonna add a new leaf in the tree.
>  	 */
> -	if (flag & EXT4_GET_BLOCKS_METADATA_NOFAIL)
> -		flags = EXT4_MB_USE_RESERVED;
> -	err = ext4_ext_create_new_leaf(handle, inode, flags, path, newext);
> +	if (gb_flags & EXT4_GET_BLOCKS_METADATA_NOFAIL)
> +		mb_flags = EXT4_MB_USE_RESERVED;
> +	err = ext4_ext_create_new_leaf(handle, inode, mb_flags, gb_flags,
> +				       path, newext);
>  	if (err)
>  		goto cleanup;
>  	depth = ext_depth(inode);
> @@ -2002,7 +2032,7 @@ has_space:
>  
>  merge:
>  	/* try to merge extents */
> -	if (!(flag & EXT4_GET_BLOCKS_PRE_IO))
> +	if (!(gb_flags & EXT4_GET_BLOCKS_PRE_IO))
>  		ext4_ext_try_to_merge(handle, inode, path, nearex);
>  
>  
> @@ -2045,7 +2075,7 @@ static int ext4_fill_fiemap_extents(struct inode *inode,
>  			path = NULL;
>  		}
>  
> -		path = ext4_ext_find_extent(inode, block, path);
> +		path = ext4_ext_find_extent(inode, block, path, 0);
>  		if (IS_ERR(path)) {
>  			up_read(&EXT4_I(inode)->i_data_sem);
>  			err = PTR_ERR(path);
> @@ -2707,7 +2737,7 @@ again:
>  		ext4_lblk_t ee_block;
>  
>  		/* find extent for this block */
> -		path = ext4_ext_find_extent(inode, end, NULL);
> +		path = ext4_ext_find_extent(inode, end, NULL, EXT4_EX_NOCACHE);
>  		if (IS_ERR(path)) {
>  			ext4_journal_stop(handle);
>  			return PTR_ERR(path);
> @@ -2749,6 +2779,7 @@ again:
>  			 */
>  			err = ext4_split_extent_at(handle, inode, path,
>  					end + 1, split_flag,
> +					EXT4_EX_NOCACHE |
>  					EXT4_GET_BLOCKS_PRE_IO |
>  					EXT4_GET_BLOCKS_METADATA_NOFAIL);
>  
> @@ -2825,7 +2856,8 @@ again:
>  				  i + 1, ext4_idx_pblock(path[i].p_idx));
>  			memset(path + i + 1, 0, sizeof(*path));
>  			bh = read_extent_tree_block(inode,
> -				ext4_idx_pblock(path[i].p_idx), depth - i - 1);
> +				ext4_idx_pblock(path[i].p_idx), depth - i - 1,
> +				EXT4_EX_NOCACHE);
>  			if (IS_ERR(bh)) {
>  				err = PTR_ERR(bh);
>  				break;
> @@ -3168,7 +3200,7 @@ static int ext4_split_extent(handle_t *handle,
>  	 * result in split of original leaf or extent zeroout.
>  	 */
>  	ext4_ext_drop_refs(path);
> -	path = ext4_ext_find_extent(inode, map->m_lblk, path);
> +	path = ext4_ext_find_extent(inode, map->m_lblk, path, 0);
>  	if (IS_ERR(path))
>  		return PTR_ERR(path);
>  	depth = ext_depth(inode);
> @@ -3552,7 +3584,7 @@ static int ext4_convert_unwritten_extents_endio(handle_t *handle,
>  		if (err < 0)
>  			goto out;
>  		ext4_ext_drop_refs(path);
> -		path = ext4_ext_find_extent(inode, map->m_lblk, path);
> +		path = ext4_ext_find_extent(inode, map->m_lblk, path, 0);
>  		if (IS_ERR(path)) {
>  			err = PTR_ERR(path);
>  			goto out;
> @@ -4039,7 +4071,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
>  	trace_ext4_ext_map_blocks_enter(inode, map->m_lblk, map->m_len, flags);
>  
>  	/* find extent for this block */
> -	path = ext4_ext_find_extent(inode, map->m_lblk, NULL);
> +	path = ext4_ext_find_extent(inode, map->m_lblk, NULL, 0);
>  	if (IS_ERR(path)) {
>  		err = PTR_ERR(path);
>  		path = NULL;
> diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
> index 7358fb3..a84804c 100644
> --- a/fs/ext4/extents_status.c
> +++ b/fs/ext4/extents_status.c
> @@ -417,7 +417,7 @@ static void ext4_es_insert_extent_ext_check(struct inode *inode,
>  	unsigned short ee_len;
>  	int depth, ee_status, es_status;
>  
> -	path = ext4_ext_find_extent(inode, es->es_lblk, NULL);
> +	path = ext4_ext_find_extent(inode, es->es_lblk, NULL, EXT4_EX_NOCACHE);
>  	if (IS_ERR(path))
>  		return;
>  
> @@ -678,6 +678,43 @@ error:
>  }
>  
>  /*
> + * ext4_es_cache_extent() inserts information into the extent status
> + * tree if and only if there isn't information about the range in
> + * question already.
> + */
> +void ext4_es_cache_extent(struct inode *inode, ext4_lblk_t lblk,
> +			  ext4_lblk_t len, ext4_fsblk_t pblk,
> +			  unsigned int status)
> +{
> +	struct extent_status *es;
> +	struct extent_status newes;
> +	ext4_lblk_t end = lblk + len - 1;
> +
> +	es_debug("cache [%u/%u) %llu %x to extent status tree of inode %lu\n",
> +		 lblk, len, pblk, status, inode->i_ino);
> +	if (!len)
> +		return;
> +
> +	BUG_ON(end < lblk);
> +
> +	write_lock(&EXT4_I(inode)->i_es_lock);
> +
> +	es = __es_tree_search(&EXT4_I(inode)->i_es_tree.root, lblk);
> +	if (es && ((es->es_lblk <= lblk) || (es->es_lblk <= end)))
> +		goto out;
> +
> +	newes.es_lblk = lblk;
> +	newes.es_len = len;
> +	ext4_es_store_pblock(&newes, pblk);
> +	ext4_es_store_status(&newes, status);
> +	trace_ext4_es_cache_extent(inode, &newes);
> +
> +	__es_insert_extent(inode, &newes);
> +out:
> +	write_unlock(&EXT4_I(inode)->i_es_lock);
> +}
> +
> +/*
>   * ext4_es_lookup_extent() looks up an extent in extent status tree.
>   *
>   * ext4_es_lookup_extent is called by ext4_map_blocks/ext4_da_map_blocks.
> diff --git a/fs/ext4/extents_status.h b/fs/ext4/extents_status.h
> index ae1be58..23348d1 100644
> --- a/fs/ext4/extents_status.h
> +++ b/fs/ext4/extents_status.h
> @@ -71,6 +71,9 @@ extern void ext4_es_init_tree(struct ext4_es_tree *tree);
>  extern int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
>  				 ext4_lblk_t len, ext4_fsblk_t pblk,
>  				 unsigned int status);
> +extern void ext4_es_cache_extent(struct inode *inode, ext4_lblk_t lblk,
> +				 ext4_lblk_t len, ext4_fsblk_t pblk,
> +				 unsigned int status);
>  extern int ext4_es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
>  				 ext4_lblk_t len);
>  extern void ext4_es_find_delayed_extent_range(struct inode *inode,
> diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
> index 49e8bdf..f99bdb8 100644
> --- a/fs/ext4/migrate.c
> +++ b/fs/ext4/migrate.c
> @@ -39,7 +39,7 @@ static int finish_range(handle_t *handle, struct inode *inode,
>  	newext.ee_block = cpu_to_le32(lb->first_block);
>  	newext.ee_len   = cpu_to_le16(lb->last_block - lb->first_block + 1);
>  	ext4_ext_store_pblock(&newext, lb->first_pblock);
> -	path = ext4_ext_find_extent(inode, lb->first_block, NULL);
> +	path = ext4_ext_find_extent(inode, lb->first_block, NULL, 0);
>  
>  	if (IS_ERR(path)) {
>  		retval = PTR_ERR(path);
> diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
> index e86dddb..7fa4d85 100644
> --- a/fs/ext4/move_extent.c
> +++ b/fs/ext4/move_extent.c
> @@ -37,7 +37,7 @@ get_ext_path(struct inode *inode, ext4_lblk_t lblock,
>  	int ret = 0;
>  	struct ext4_ext_path *path;
>  
> -	path = ext4_ext_find_extent(inode, lblock, *orig_path);
> +	path = ext4_ext_find_extent(inode, lblock, *orig_path, EXT4_EX_NOCACHE);
>  	if (IS_ERR(path))
>  		ret = PTR_ERR(path);
>  	else if (path[ext_depth(inode)].p_ext == NULL)
> diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
> index 47a355b..d892b55 100644
> --- a/include/trace/events/ext4.h
> +++ b/include/trace/events/ext4.h
> @@ -2192,7 +2192,7 @@ TRACE_EVENT(ext4_ext_remove_space_done,
>  		  (unsigned short) __entry->eh_entries)
>  );
>  
> -TRACE_EVENT(ext4_es_insert_extent,
> +DECLARE_EVENT_CLASS(ext4__es_extent,
>  	TP_PROTO(struct inode *inode, struct extent_status *es),
>  
>  	TP_ARGS(inode, es),
> @@ -2222,6 +2222,18 @@ TRACE_EVENT(ext4_es_insert_extent,
>  		  __entry->pblk, show_extent_status(__entry->status))
>  );
>  
> +DEFINE_EVENT(ext4__es_extent, ext4_es_insert_extent,
> +	TP_PROTO(struct inode *inode, struct extent_status *es),
> +
> +	TP_ARGS(inode, es)
> +);
> +
> +DEFINE_EVENT(ext4__es_extent, ext4_es_cache_extent,
> +	TP_PROTO(struct inode *inode, struct extent_status *es),
> +
> +	TP_ARGS(inode, es)
> +);
> +
>  TRACE_EVENT(ext4_es_remove_extent,
>  	TP_PROTO(struct inode *inode, ext4_lblk_t lblk, ext4_lblk_t len),
>  
> -- 
> 1.7.12.rc0.22.gcdd159b
> 

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

* Re: [RFC PATCH 3/3] ext4: cache all of an extent tree's leaf block upon reading
  2013-07-11  4:39 ` [RFC PATCH 3/3] ext4: cache all of an extent tree's leaf block upon reading Theodore Ts'o
  2013-07-11 12:52   ` Zheng Liu
@ 2013-07-11 18:54   ` Zach Brown
  2013-07-11 19:33     ` Theodore Ts'o
  1 sibling, 1 reply; 8+ messages in thread
From: Zach Brown @ 2013-07-11 18:54 UTC (permalink / raw)
  To: Theodore Ts'o; +Cc: Ext4 Developers List, Zheng Liu, Zheng Liu

> @@ -490,6 +491,31 @@ __read_extent_tree_block(const char *function, unsigned int line,
>  	if (err)
>  		goto errout;
>  	set_buffer_verified(bh);
> +	/*
> +	 * If this is a leaf block, cache all of its entries
> +	 */
> +	if (!(flags & EXT4_EX_NOCACHE) && depth == 0) {
> +		struct ext4_extent_header *eh = ext_block_hdr(bh);
> +		struct ext4_extent *ex = EXT_FIRST_EXTENT(eh);
> +		int i;
> +
> +		for (i = eh->eh_entries; i > 0; i--, ex++) {
> +			unsigned int status = EXTENT_STATUS_WRITTEN;
> +			ext4_lblk_t prev = 0, lblk = le32_to_cpu(ex->ee_block);
> +			int len = ext4_ext_get_actual_len(ex);
> +
> +			if (prev && (prev != lblk))
> +				ext4_es_cache_extent(inode, prev,
> +						     lblk - prev, ~0,
> +						     EXTENT_STATUS_HOLE);
> +
> +			if (ext4_ext_is_uninitialized(ex))
> +				status = EXTENT_STATUS_UNWRITTEN;
> +			ext4_es_cache_extent(inode, lblk, len,
> +					     ext4_ext_pblock(ex), status);
> +			prev = lblk + len;
> +		}
> +	}

Isn't prev going to be reinitialized to 0 for every extent?

- z

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

* Re: [RFC PATCH 3/3] ext4: cache all of an extent tree's leaf block upon reading
  2013-07-11 18:54   ` Zach Brown
@ 2013-07-11 19:33     ` Theodore Ts'o
  0 siblings, 0 replies; 8+ messages in thread
From: Theodore Ts'o @ 2013-07-11 19:33 UTC (permalink / raw)
  To: Zach Brown; +Cc: Ext4 Developers List, Zheng Liu, Zheng Liu

On Thu, Jul 11, 2013 at 11:54:23AM -0700, Zach Brown wrote:
> 
> Isn't prev going to be reinitialized to 0 for every extent?

Whoops, nice catch.  I'll fix this in my next spin of the patches.

	     	     	      	   - Ted

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

end of thread, other threads:[~2013-07-11 19:34 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-07-11  4:39 [RFC PATCH 1/3] ext4: refactor code to read the extent tree block Theodore Ts'o
2013-07-11  4:39 ` [RFC PATCH 2/3] ext4: use unsigned int for es_status values Theodore Ts'o
2013-07-11 12:48   ` Zheng Liu
2013-07-11  4:39 ` [RFC PATCH 3/3] ext4: cache all of an extent tree's leaf block upon reading Theodore Ts'o
2013-07-11 12:52   ` Zheng Liu
2013-07-11 18:54   ` Zach Brown
2013-07-11 19:33     ` Theodore Ts'o
2013-07-11 12:41 ` [RFC PATCH 1/3] ext4: refactor code to read the extent tree block Zheng Liu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.