linux-ext4.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/6] ext4: status extents
@ 2012-04-18  7:07 Allison Henderson
  2012-04-18  7:07 ` [PATCH 1/6] ext4: add two structures supporting status extent tree Allison Henderson
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Allison Henderson @ 2012-04-18  7:07 UTC (permalink / raw)
  To: linux-ext4; +Cc: Allison Henderson

This set is based on the earlier delayed extent tree, but has
been renamed to a "status extent" scheme.  The plan is that the
tree will be expanded to track allocated extents and also
support extent locks.  Thus status extents seemed like a
more appropriate name.

Allison Henderson (6):
  ext4: add two structures supporting status extent tree
  ext4: add operations on status extent tree
  ext4: initialize status extent tree
  ext4: let ext4 maintian status extent trees
  ext4: reimplement fiemap on status extent tree
  ext4: reimplement ext4_find_delay_alloc_range on status extent tree

 fs/ext4/Makefile         |    2 +-
 fs/ext4/ext4.h           |    9 +-
 fs/ext4/ext4_extents.h   |    3 +-
 fs/ext4/extents.c        |  297 ++++-----------------------------
 fs/ext4/indirect.c       |    3 +
 fs/ext4/inode.c          |   83 ++++------
 fs/ext4/status_extents.c |  417 ++++++++++++++++++++++++++++++++++++++++++++++
 fs/ext4/status_extents.h |   40 +++++
 fs/ext4/super.c          |   13 ++-
 9 files changed, 545 insertions(+), 322 deletions(-)
 create mode 100644 fs/ext4/status_extents.c
 create mode 100644 fs/ext4/status_extents.h


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

* [PATCH 1/6] ext4: add two structures supporting status extent tree
  2012-04-18  7:07 [PATCH 0/6] ext4: status extents Allison Henderson
@ 2012-04-18  7:07 ` Allison Henderson
  2012-04-18  7:07 ` [PATCH 2/6] ext4: add operations on " Allison Henderson
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Allison Henderson @ 2012-04-18  7:07 UTC (permalink / raw)
  To: linux-ext4; +Cc: Allison Henderson, Yongqiang Yang

This patch adds two structures that supports status extent tree and
status_extent_info to inode_info.

Signed-off-by: Yongqiang Yang <xiaoqiangnk@gmail.com>
Signed-off-by: Allison Henderson <achender@linux.vnet.ibm.com>
---
:100644 100644 1bbd2ca... 704021e... M	fs/ext4/ext4.h
:000000 100644 0000000... cbf96ed... A	fs/ext4/status_extents.h
 fs/ext4/ext4.h           |    5 +++++
 fs/ext4/status_extents.h |   22 ++++++++++++++++++++++
 2 files changed, 27 insertions(+), 0 deletions(-)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 1bbd2ca..704021e 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -782,6 +782,8 @@ struct ext4_ext_cache {
 	__u32		ec_len; /* must be 32bit to return holes */
 };
 
+#include "status_extents.h"
+
 /*
  * fourth extended file system inode data in memory
  */
@@ -859,6 +861,9 @@ struct ext4_inode_info {
 	struct list_head i_prealloc_list;
 	spinlock_t i_prealloc_lock;
 
+	/* delayed extents */
+	struct ext4_se_tree i_se_tree;
+
 	/* ialloc */
 	ext4_group_t	i_last_alloc_group;
 
diff --git a/fs/ext4/status_extents.h b/fs/ext4/status_extents.h
new file mode 100644
index 0000000..cbf96ed
--- /dev/null
+++ b/fs/ext4/status_extents.h
@@ -0,0 +1,22 @@
+/*
+ *  fs/ext4/status_extents.h
+ *
+ * Written by Yongqiang Yang <xiaoqiangnk@gmail.com>
+ *
+ */
+
+#ifndef _EXT4_STATUS_EXTENTS_H
+#define _EXT4_STATUS_EXTENTS_H
+
+struct status_extent {
+	struct rb_node rb_node;
+	ext4_lblk_t start;	/* first block extent covers */
+	ext4_lblk_t len;	/* length of extent in block */
+};
+
+struct ext4_se_tree {
+	struct rb_root root;
+	struct status_extent *cache_se;	/* recently accessed extent */
+};
+
+#endif /* _EXT4_STATUS_EXTENTS_H */
-- 
1.7.1


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

* [PATCH 2/6] ext4: add operations on status extent tree
  2012-04-18  7:07 [PATCH 0/6] ext4: status extents Allison Henderson
  2012-04-18  7:07 ` [PATCH 1/6] ext4: add two structures supporting status extent tree Allison Henderson
@ 2012-04-18  7:07 ` Allison Henderson
  2012-04-18  7:07 ` [PATCH 3/6] ext4: initialize " Allison Henderson
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Allison Henderson @ 2012-04-18  7:07 UTC (permalink / raw)
  To: linux-ext4; +Cc: Allison Henderson, Yongqiang Yang

This patch adds operations on a status extent tree.

Signed-off-by: Yongqiang Yang <xiaoqiangnk@gmail.com>
Signed-off-by: Allison Henderson <achender@linux.vnet.ibm.com>
---
:100644 100644 56fd8f86.. 55482c1... M	fs/ext4/Makefile
:000000 100644 0000000... 938e935... A	fs/ext4/status_extents.c
:100644 100644 cbf96ed... 415befd... M	fs/ext4/status_extents.h
 fs/ext4/Makefile         |    2 +-
 fs/ext4/status_extents.c |  417 ++++++++++++++++++++++++++++++++++++++++++++++
 fs/ext4/status_extents.h |   18 ++
 3 files changed, 436 insertions(+), 1 deletions(-)

diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile
index 56fd8f8..55482c1 100644
--- a/fs/ext4/Makefile
+++ b/fs/ext4/Makefile
@@ -7,7 +7,7 @@ obj-$(CONFIG_EXT4_FS) += ext4.o
 ext4-y	:= balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o page-io.o \
 		ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \
 		ext4_jbd2.o migrate.o mballoc.o block_validity.o move_extent.o \
-		mmp.o indirect.o
+		mmp.o indirect.o status_extents.o
 
 ext4-$(CONFIG_EXT4_FS_XATTR)		+= xattr.o xattr_user.o xattr_trusted.o
 ext4-$(CONFIG_EXT4_FS_POSIX_ACL)	+= acl.o
diff --git a/fs/ext4/status_extents.c b/fs/ext4/status_extents.c
new file mode 100644
index 0000000..938e935
--- /dev/null
+++ b/fs/ext4/status_extents.c
@@ -0,0 +1,417 @@
+/*
+ *  fs/ext4/status_extents.c
+ *
+ * Written by Yongqiang Yang <xiaoqiangnk@gmail.com>
+ *
+ * Ext4 status extents core functions.
+ */
+#include <linux/rbtree.h>
+#include "ext4.h"
+#include "status_extents.h"
+#include "ext4_extents.h"
+
+/*
+ * status extent implementation for ext4.
+ *
+ *
+ * ==========================================================================
+ * Status extents encompass delayed extents and extent locks
+ *
+ * 1. Why delayed extent implementation ?
+ *
+ * Without delayed extent, ext4 identifies a delayed extent by looking up
+ * page cache, this has several deficiencies - complicated, buggy, and
+ * inefficient code.
+ *
+ * FIEMAP, SEEK_HOLE/DATA, bigalloc, punch hole and writeout all need to know if
+ * a block or a range of blocks are belonged to a delayed extent.
+ *
+ * Let us have a look at how they do without delayed extents implementation.
+ *   --	FIEMAP
+ *	FIEMAP looks up page cache to identify delayed allocations from holes.
+ *
+ *   --	SEEK_HOLE/DATA
+ *	SEEK_HOLE/DATA has the same problem as FIEMAP.
+ *
+ *   --	bigalloc
+ *	bigalloc looks up page cache to figure out if a block is already
+ *	under delayed allocation or not to determine whether quota reserving
+ *	is needed for the cluster.
+ *
+ *   -- punch hole
+ *	punch hole looks up page cache to identify a delayed extent.
+ *
+ *   --	writeout
+ *	Writeout looks up whole page cache to see if a buffer is mapped, If
+ *	there are not very many delayed buffers, then it is time comsuming.
+ *
+ * With delayed extents implementation, FIEMAP, SEEK_HOLE/DATA, bigalloc and
+ * writeout can figure out if a block or a range of blocks is under delayed
+ * allocation(belonged to a delayed extent) or not by searching the delayed
+ * extent tree.
+ *
+ *
+ * ==========================================================================
+ * 2. ext4 delayed extents impelmentation
+ *
+ *   --	delayed extent
+ *	A delayed extent is a range of blocks which are contiguous logically and
+ *	under delayed allocation.  Unlike extent in ext4, delayed extent in ext4
+ *	is a in-memory struct, there is no corresponding on-disk data.  There is
+ *	no limit on length of delayed extent, so a delayed extent can contain as
+ *	many blocks as they are contiguous logically.
+ *
+ *   --	delayed extent tree
+ *	Every inode has a delayed extent tree and all under delayed allocation
+ *	blocks are added to the tree as dealyed extents.  Delayed extents in
+ *	the tree are ordered by logical block no.
+ *
+ *   --	operations on a delayed extent tree
+ *	There are three operations on a delayed extent tree: find next delayed
+ *	extent, adding a space(a range of blocks) and removing a space.
+ *
+ *   --	race on a delayed extent tree
+ *	Delayed extent tree is protected inode->i_data_sem like extent tree.
+ *
+ *
+ * ==========================================================================
+ * 3. performance analysis
+ *   --	overhead
+ *	1. Apart from operations on a delayed extent tree, we need to
+ *	down_write(inode->i_data_sem) in delayed write path to maintain delayed
+ *	extent tree, this can have impact on parallel read-write and write-write
+ *
+ *	2. There is a cache extent for write access, so if writes are not very
+ *	random, adding space operaions are in O(1) time.
+ *
+ *   -- gain
+ *	3. Code is much simpler, more readable, more maintainable and
+ *      more efficient.
+ */
+
+static struct kmem_cache *ext4_se_cachep;
+
+int __init ext4_init_se(void)
+{
+	ext4_se_cachep = KMEM_CACHE(status_extent, SLAB_RECLAIM_ACCOUNT);
+	if (ext4_se_cachep == NULL)
+		return -ENOMEM;
+	return 0;
+}
+
+void ext4_exit_se(void)
+{
+	if (ext4_se_cachep)
+		kmem_cache_destroy(ext4_se_cachep);
+}
+
+void ext4_se_init_tree(struct ext4_se_tree *tree)
+{
+	tree->root = RB_ROOT;
+	tree->cache_se = NULL;
+}
+
+#ifdef SE_DEBUG
+static void ext4_se_print_tree(struct inode *inode)
+{
+	struct ext4_se_tree *tree;
+	struct rb_node *node;
+
+	printk(KERN_DEBUG "status extents for inode %lu:", inode->i_ino);
+	tree = &EXT4_I(inode)->i_se_tree;
+	node = rb_first(&tree->root);
+	while (node) {
+		struct status_extent *se;
+		se = rb_entry(node, struct status_extent, rb_node);
+		printk(KERN_DEBUG " [%u/%u)", se->start, se->len);
+		node = rb_next(node);
+	}
+	printk(KERN_DEBUG "\n");
+}
+#else
+#define ext4_se_print_tree(inode)
+#endif
+
+static inline ext4_lblk_t status_extent_end(struct status_extent *se)
+{
+	if (se->start + se->len < se->start)
+		return (ext4_lblk_t)-1;
+	return se->start + se->len;
+}
+
+/*
+ * search through the tree for an delayed_extent with a given offset.  If
+ * it can't be found, try to find next extent.
+ */
+static struct status_extent *__se_tree_search(struct rb_root *root,
+						ext4_lblk_t offset)
+{
+	struct rb_node *node = root->rb_node;
+	struct status_extent *se = NULL;
+
+	while (node) {
+		se = rb_entry(node, struct status_extent, rb_node);
+		if (offset < se->start)
+			node = node->rb_left;
+		else if (offset >= status_extent_end(se))
+			node = node->rb_right;
+		else
+			return se;
+	}
+
+	if (se && offset < se->start)
+		return se;
+
+	if (se && offset >= status_extent_end(se)) {
+		node = rb_next(&se->rb_node);
+		return node ? rb_entry(node, struct status_extent, rb_node) :
+			      NULL;
+	}
+
+	return NULL;
+}
+
+/*
+ * ext4_se_find_extent: find the 1st delayed extent covering @se->start
+ * if it exists, otherwise, the next extent after @se->start.
+ *
+ * @inode: the inode which owns delayed extents
+ * @se:
+ *
+ * Returns next block beyond the found extent.
+ * Delayed extent is returned via @se.
+ */
+ext4_lblk_t ext4_se_find_extent(struct inode *inode, struct status_extent *se)
+{
+	struct ext4_se_tree *tree;
+	struct status_extent *se1;
+	struct rb_node *node;
+
+	se->len = 0;
+	tree = &EXT4_I(inode)->i_se_tree;
+	se1 = __se_tree_search(&tree->root, se->start);
+	if (se1) {
+		tree->cache_se = se1;
+		se->start = se1->start;
+		se->len = se1->len;
+		node = rb_next(&se1->rb_node);
+		if (node) {
+			se1 = rb_entry(node, struct status_extent, rb_node);
+			return se1->start;
+		}
+	}
+
+	return EXT_MAX_BLOCKS;
+}
+
+static struct status_extent *
+ext4_se_alloc_extent(ext4_lblk_t start, ext4_lblk_t len)
+{
+	struct status_extent *se;
+	se = kmem_cache_alloc(ext4_se_cachep, GFP_NOFS);
+	if (se == NULL)
+		return NULL;
+	se->start = start;
+	se->len = len;
+	return se;
+}
+
+static void ext4_se_free_extent(struct status_extent *se)
+{
+	kmem_cache_free(ext4_se_cachep, se);
+}
+
+static void ext4_se_try_to_merge_left(struct ext4_se_tree *tree,
+				      struct status_extent *se)
+{
+	struct status_extent *se1;
+	struct rb_node *node;
+
+	node = rb_prev(&se->rb_node);
+	if (!node)
+		return;
+
+	se1 = rb_entry(node, struct status_extent, rb_node);
+	if (status_extent_end(se1) == se->start) {
+		se1->len += se->len;
+		rb_erase(&se->rb_node, &tree->root);
+		if (se == tree->cache_se)
+			tree->cache_se = se1;
+		ext4_se_free_extent(se);
+	}
+}
+
+static void ext4_se_try_to_merge_right(struct ext4_se_tree *tree,
+				       struct status_extent *se)
+{
+	struct status_extent *se1;
+	struct rb_node *node;
+
+	node = rb_next(&se->rb_node);
+	if (!node)
+		return;
+
+	se1 = rb_entry(node, struct status_extent, rb_node);
+	if (se1->start == status_extent_end(se)) {
+		se->len += se1->len;
+		rb_erase(node, &tree->root);
+		if (se1 == tree->cache_se)
+			tree->cache_se = se;
+		ext4_se_free_extent(se1);
+	}
+}
+
+/*
+ * ext4_se_add_space: adds a space to a delayed extent tree.
+ * Caller holds inode->i_data_sem.
+ *
+ * ext4_se_add_space is callyed by ext4_dealyed_write_begin and
+ * ext4_se_remove_space.
+ *
+ * Return 0 on success, error code on failure.
+ */
+int ext4_se_add_space(struct inode *inode, ext4_lblk_t offset, ext4_lblk_t len)
+{
+	struct ext4_se_tree *tree = &EXT4_I(inode)->i_se_tree;
+	struct rb_node **p = &tree->root.rb_node;
+	struct rb_node *parent = NULL;
+	struct status_extent *se;
+	ext4_lblk_t end = offset + len;
+
+	BUG_ON(end <= offset);
+
+	se = tree->cache_se;
+	se_debug("add [%u/%u) to status extent tree of inode %lu\n",
+		 offset, len, inode->i_ino);
+
+	if (se && status_extent_end(se) == offset) {
+		se_debug("cached by [%u/%u)\n", se->start, se->len);
+		se->len += len;
+		ext4_se_try_to_merge_right(tree, se);
+		goto out;
+	} else if (se && se->start == end) {
+		se_debug("cached by [%u/%u)\n", se->start, se->len);
+		se->start = offset;
+		se->len += len;
+		ext4_se_try_to_merge_left(tree, se);
+		goto out;
+	} else if (se && se->start <= offset &&
+		   status_extent_end(se) >= end) {
+		se_debug("cached by [%u/%u)\n", se->start, se->len);
+		goto out;
+	}
+
+	while (*p) {
+		parent = *p;
+		se = rb_entry(parent, struct status_extent, rb_node);
+
+		if (offset < se->start) {
+			if (end == se->start) {
+				se->len += len;
+				se->start = offset;
+				goto out;
+			}
+			p = &(*p)->rb_left;
+		} else if (offset >= status_extent_end(se)) {
+			if (status_extent_end(se) == offset) {
+				se->len += len;
+				goto out;
+			}
+			p = &(*p)->rb_right;
+		} else
+			goto out;
+	}
+
+	se = ext4_se_alloc_extent(offset, len);
+	if (!se)
+		return -ENOMEM;
+	rb_link_node(&se->rb_node, parent, p);
+	rb_insert_color(&se->rb_node, &tree->root);
+
+out:
+	tree->cache_se = se;
+	ext4_se_print_tree(inode);
+
+	return 0;
+}
+
+/*
+ * ext4_se_remove_space() removes a space from a delayed extent tree.
+ * Caller holds inode->i_data_sem.
+ *
+ * Return 0 on success, error code on failure.
+ */
+int ext4_se_remove_space(struct inode *inode, ext4_lblk_t offset,
+			 ext4_lblk_t len)
+{
+	struct rb_node *node;
+	struct ext4_se_tree *tree;
+	struct status_extent *se;
+	struct status_extent orig_se;
+	ext4_lblk_t len1, len2, end;
+
+	se_debug("remove [%u/%u) from status extent tree of inode %lu\n",
+		 offset, len, inode->i_ino);
+
+	end = offset + len;
+	BUG_ON(end <= offset);
+	tree = &EXT4_I(inode)->i_se_tree;
+	se = __se_tree_search(&tree->root, offset);
+	if (!se)
+		goto out;
+
+	/* Simply invalidate cache_se. */
+	tree->cache_se = NULL;
+
+	orig_se.start = se->start;
+	orig_se.len = se->len;
+	len1 = offset > se->start ? offset - se->start : 0;
+	len2 = status_extent_end(se) > end ?
+	       status_extent_end(se) - end : 0;
+	if (len1 > 0)
+		se->len = len1;
+	if (len2 > 0) {
+		if (len1 > 0) {
+			int err;
+			err = ext4_se_add_space(inode, end, len2);
+			if (err) {
+				se->start = orig_se.start;
+				se->len = orig_se.len;
+				return err;
+			}
+		} else {
+			se->start = end;
+			se->len = len2;
+		}
+		goto out;
+	}
+
+	if (len1 > 0) {
+		node = rb_next(&se->rb_node);
+		if (!node)
+			se = rb_entry(node, struct status_extent, rb_node);
+		else
+			se = NULL;
+	}
+
+	while (se && status_extent_end(se) <= end) {
+		node = rb_next(&se->rb_node);
+		rb_erase(&se->rb_node, &tree->root);
+		ext4_se_free_extent(se);
+		if (!node) {
+			se = NULL;
+			break;
+		}
+		se = rb_entry(node, struct status_extent, rb_node);
+	}
+
+	if (se && se->start < end) {
+		len1 = status_extent_end(se) - end;
+		se->start = end;
+		se->len = len1;
+	}
+
+out:
+	ext4_se_print_tree(inode);
+	return 0;
+}
diff --git a/fs/ext4/status_extents.h b/fs/ext4/status_extents.h
index cbf96ed..415befd 100644
--- a/fs/ext4/status_extents.h
+++ b/fs/ext4/status_extents.h
@@ -8,6 +8,13 @@
 #ifndef _EXT4_STATUS_EXTENTS_H
 #define _EXT4_STATUS_EXTENTS_H
 
+#define SE_DEBUG
+#ifdef SE_DEBUG
+#define se_debug(a...)         printk(a)
+#else
+#define se_debug(a...)
+#endif
+
 struct status_extent {
 	struct rb_node rb_node;
 	ext4_lblk_t start;	/* first block extent covers */
@@ -19,4 +26,15 @@ struct ext4_se_tree {
 	struct status_extent *cache_se;	/* recently accessed extent */
 };
 
+extern int __init ext4_init_se(void);
+extern void ext4_exit_se(void);
+extern void ext4_se_init_tree(struct ext4_se_tree *tree);
+
+extern int ext4_se_add_space(struct inode *inode, ext4_lblk_t start,
+				ext4_lblk_t len);
+extern int ext4_se_remove_space(struct inode *inode, ext4_lblk_t start,
+				ext4_lblk_t len);
+extern ext4_lblk_t ext4_se_find_extent(struct inode *inode,
+				struct status_extent *se);
+
 #endif /* _EXT4_STATUS_EXTENTS_H */
-- 
1.7.1


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

* [PATCH 3/6] ext4: initialize status extent tree
  2012-04-18  7:07 [PATCH 0/6] ext4: status extents Allison Henderson
  2012-04-18  7:07 ` [PATCH 1/6] ext4: add two structures supporting status extent tree Allison Henderson
  2012-04-18  7:07 ` [PATCH 2/6] ext4: add operations on " Allison Henderson
@ 2012-04-18  7:07 ` Allison Henderson
  2012-04-18  7:07 ` [PATCH 4/6] ext4: let ext4 maintian status extent trees Allison Henderson
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Allison Henderson @ 2012-04-18  7:07 UTC (permalink / raw)
  To: linux-ext4; +Cc: Allison Henderson, Yongqiang Yang

Let ext4 initialize status extent tree of a inode.

Signed-off-by: Yongqiang Yang <xiaoqiangnk@gmail.com>
Signed-off-by: Allison Henderson <achender@linux.vnet.ibm.com>
---
:100644 100644 db2cd3f... da223a1... M	fs/ext4/super.c
 fs/ext4/super.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index db2cd3f..da223a1 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -898,6 +898,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
 	memset(&ei->i_cached_extent, 0, sizeof(struct ext4_ext_cache));
 	INIT_LIST_HEAD(&ei->i_prealloc_list);
 	spin_lock_init(&ei->i_prealloc_lock);
+	ext4_se_init_tree(&ei->i_se_tree);
 	ei->i_reserved_data_blocks = 0;
 	ei->i_reserved_meta_blocks = 0;
 	ei->i_allocated_meta_blocks = 0;
-- 
1.7.1


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

* [PATCH 4/6] ext4: let ext4 maintian status extent trees
  2012-04-18  7:07 [PATCH 0/6] ext4: status extents Allison Henderson
                   ` (2 preceding siblings ...)
  2012-04-18  7:07 ` [PATCH 3/6] ext4: initialize " Allison Henderson
@ 2012-04-18  7:07 ` Allison Henderson
  2012-04-18  7:07 ` [PATCH 5/6] ext4: reimplement fiemap on status extent tree Allison Henderson
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Allison Henderson @ 2012-04-18  7:07 UTC (permalink / raw)
  To: linux-ext4; +Cc: Allison Henderson, Yongqiang Yang

This patch let ext4 maintain status extent trees.

Signed-off-by: Yongqiang Yang <xiaoqiangnk@gmail.com>
Signed-off-by: Allison Henderson <achender@linux.vnet.ibm.com>
---
:100644 100644 ad39627... 2322ff8... M	fs/ext4/extents.c
:100644 100644 3cfc73f... 47d78b8... M	fs/ext4/indirect.c
:100644 100644 1380cd2... adeae2f... M	fs/ext4/inode.c
:100644 100644 da223a1... d1a438b... M	fs/ext4/super.c
 fs/ext4/extents.c  |    2 ++
 fs/ext4/indirect.c |    3 +++
 fs/ext4/inode.c    |   30 ++++++++++++++++++++++++++++--
 fs/ext4/super.c    |   12 +++++++++++-
 4 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index ad39627..2322ff8 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4227,6 +4227,8 @@ void ext4_ext_truncate(struct inode *inode)
 
 	last_block = (inode->i_size + sb->s_blocksize - 1)
 			>> EXT4_BLOCK_SIZE_BITS(sb);
+	err = ext4_se_remove_space(inode, last_block,
+				   EXT_MAX_BLOCKS - last_block);
 	err = ext4_ext_remove_space(inode, last_block);
 
 	/* In a multi-transaction truncate, we only make the final
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
index 3cfc73f..47d78b8 100644
--- a/fs/ext4/indirect.c
+++ b/fs/ext4/indirect.c
@@ -22,6 +22,7 @@
 
 #include <linux/module.h>
 #include "ext4_jbd2.h"
+#include "ext4_extents.h"
 #include "truncate.h"
 
 #include <trace/events/ext4.h>
@@ -1399,6 +1400,8 @@ void ext4_ind_truncate(struct inode *inode)
 	down_write(&ei->i_data_sem);
 
 	ext4_discard_preallocations(inode);
+	ext4_se_remove_space(inode, last_block,
+			     EXT_MAX_BLOCKS - last_block);
 
 	/*
 	 * The orphan list entry will now protect us from any crash which
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 1380cd2..adeae2f 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -484,7 +484,16 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
 	up_read((&EXT4_I(inode)->i_data_sem));
 
 	if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) {
-		int ret = check_block_validity(inode, map);
+		int ret;
+		if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) {
+			/* delayed alloc may be allocated by fallocate and
+			 * coverted to initialized by directIO.
+			 * we need to handle delayed extent here.
+			 */
+			down_write((&EXT4_I(inode)->i_data_sem));
+			goto delayed_mapped;
+		}
+		ret = check_block_validity(inode, map);
 		if (ret != 0)
 			return ret;
 	}
@@ -566,8 +575,16 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
 		 * set the BH_Da_Mapped bit on them. Its important to do this
 		 * under the protection of i_data_sem.
 		 */
-		if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED)
+		if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) {
+			int ret;
 			set_buffers_da_mapped(inode, map);
+delayed_mapped:
+			/* delayed allocation blocks has been allocated */
+			ret = ext4_se_remove_space(inode, map->m_lblk,
+						   map->m_len);
+			if (ret < 0)
+				retval = ret;
+		}
 	}
 
 	up_write((&EXT4_I(inode)->i_data_sem));
@@ -1668,6 +1685,7 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock,
 			      struct buffer_head *bh)
 {
 	int retval;
+	int ret;
 	sector_t invalid_block = ~((sector_t) 0xffff);
 
 	if (invalid_block < ext4_blocks_count(EXT4_SB(inode->i_sb)->s_es))
@@ -1714,6 +1732,14 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock,
 out_unlock:
 	up_read((&EXT4_I(inode)->i_data_sem));
 
+	if (retval == 0) {
+		down_write((&EXT4_I(inode)->i_data_sem));
+		ret = ext4_se_add_space(inode, map->m_lblk, map->m_len);
+		up_write((&EXT4_I(inode)->i_data_sem));
+		if (ret)
+			return ret;
+	}
+
 	return retval;
 }
 
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index da223a1..d1a438b 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -49,6 +49,7 @@
 #include "xattr.h"
 #include "acl.h"
 #include "mballoc.h"
+#include "ext4_extents.h"
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/ext4.h>
@@ -983,6 +984,7 @@ void ext4_clear_inode(struct inode *inode)
 	end_writeback(inode);
 	dquot_drop(inode);
 	ext4_discard_preallocations(inode);
+	ext4_se_remove_space(inode, 0, EXT_MAX_BLOCKS);
 	if (EXT4_I(inode)->jinode) {
 		jbd2_journal_release_jbd_inode(EXT4_JOURNAL(inode),
 					       EXT4_I(inode)->jinode);
@@ -5066,9 +5068,14 @@ static int __init ext4_init_fs(void)
 		init_waitqueue_head(&ext4__ioend_wq[i]);
 	}
 
-	err = ext4_init_pageio();
+	err = ext4_init_se();
 	if (err)
 		return err;
+
+	err = ext4_init_pageio();
+	if (err)
+		goto out8;
+
 	err = ext4_init_system_zone();
 	if (err)
 		goto out7;
@@ -5120,6 +5127,9 @@ out6:
 	ext4_exit_system_zone();
 out7:
 	ext4_exit_pageio();
+out8:
+	ext4_exit_se();
+
 	return err;
 }
 
-- 
1.7.1


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

* [PATCH 5/6] ext4: reimplement fiemap on status extent tree
  2012-04-18  7:07 [PATCH 0/6] ext4: status extents Allison Henderson
                   ` (3 preceding siblings ...)
  2012-04-18  7:07 ` [PATCH 4/6] ext4: let ext4 maintian status extent trees Allison Henderson
@ 2012-04-18  7:07 ` Allison Henderson
  2012-04-18  7:07 ` [PATCH 6/6] ext4: reimplement ext4_find_delay_alloc_range " Allison Henderson
  2012-04-19  1:56 ` [PATCH 0/6] ext4: status extents Darrick J. Wong
  6 siblings, 0 replies; 8+ messages in thread
From: Allison Henderson @ 2012-04-18  7:07 UTC (permalink / raw)
  To: linux-ext4; +Cc: Allison Henderson, Yongqiang Yang

This patch reimplements fiemap on status extent tree.

Signed-off-by: Yongqiang Yang <xiaoqiangnk@gmail.com>
Signed-off-by: Allison Henderson <achender@linux.vnet.ibm.com>
---
:100644 100644 2322ff8... cee94ce... M	fs/ext4/extents.c
 fs/ext4/extents.c |  186 +++++++----------------------------------------------
 1 files changed, 23 insertions(+), 163 deletions(-)

diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 2322ff8..cee94ce 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4448,193 +4448,53 @@ static int ext4_ext_fiemap_cb(struct inode *inode, ext4_lblk_t next,
 		       struct ext4_ext_cache *newex, struct ext4_extent *ex,
 		       void *data)
 {
+	struct status_extent se;
 	__u64	logical;
 	__u64	physical;
 	__u64	length;
 	__u32	flags = 0;
+	ext4_lblk_t next_del;
 	int		ret = 0;
 	struct fiemap_extent_info *fieinfo = data;
 	unsigned char blksize_bits;
 
-	blksize_bits = inode->i_sb->s_blocksize_bits;
-	logical = (__u64)newex->ec_block << blksize_bits;
+	se.start = newex->ec_block;
+	down_read(&EXT4_I(inode)->i_data_sem);
+	next_del = ext4_se_find_extent(inode, &se);
+	up_read(&EXT4_I(inode)->i_data_sem);
 
+	next = min(next_del, next);
 	if (newex->ec_start == 0) {
 		/*
 		 * No extent in extent-tree contains block @newex->ec_start,
 		 * then the block may stay in 1)a hole or 2)delayed-extent.
-		 *
-		 * Holes or delayed-extents are processed as follows.
-		 * 1. lookup dirty pages with specified range in pagecache.
-		 *    If no page is got, then there is no delayed-extent and
-		 *    return with EXT_CONTINUE.
-		 * 2. find the 1st mapped buffer,
-		 * 3. check if the mapped buffer is both in the request range
-		 *    and a delayed buffer. If not, there is no delayed-extent,
-		 *    then return.
-		 * 4. a delayed-extent is found, the extent will be collected.
 		 */
-		ext4_lblk_t	end = 0;
-		pgoff_t		last_offset;
-		pgoff_t		offset;
-		pgoff_t		index;
-		pgoff_t		start_index = 0;
-		struct page	**pages = NULL;
-		struct buffer_head *bh = NULL;
-		struct buffer_head *head = NULL;
-		unsigned int nr_pages = PAGE_SIZE / sizeof(struct page *);
-
-		pages = kmalloc(PAGE_SIZE, GFP_KERNEL);
-		if (pages == NULL)
-			return -ENOMEM;
-
-		offset = logical >> PAGE_SHIFT;
-repeat:
-		last_offset = offset;
-		head = NULL;
-		ret = find_get_pages_tag(inode->i_mapping, &offset,
-					PAGECACHE_TAG_DIRTY, nr_pages, pages);
-
-		if (!(flags & FIEMAP_EXTENT_DELALLOC)) {
-			/* First time, try to find a mapped buffer. */
-			if (ret == 0) {
-out:
-				for (index = 0; index < ret; index++)
-					page_cache_release(pages[index]);
-				/* just a hole. */
-				kfree(pages);
-				return EXT_CONTINUE;
-			}
-			index = 0;
-
-next_page:
-			/* Try to find the 1st mapped buffer. */
-			end = ((__u64)pages[index]->index << PAGE_SHIFT) >>
-				  blksize_bits;
-			if (!page_has_buffers(pages[index]))
-				goto out;
-			head = page_buffers(pages[index]);
-			if (!head)
-				goto out;
-
-			index++;
-			bh = head;
-			do {
-				if (end >= newex->ec_block +
-					newex->ec_len)
-					/* The buffer is out of
-					 * the request range.
-					 */
-					goto out;
-
-				if (buffer_mapped(bh) &&
-				    end >= newex->ec_block) {
-					start_index = index - 1;
-					/* get the 1st mapped buffer. */
-					goto found_mapped_buffer;
-				}
-
-				bh = bh->b_this_page;
-				end++;
-			} while (bh != head);
-
-			/* No mapped buffer in the range found in this page,
-			 * We need to look up next page.
-			 */
-			if (index >= ret) {
-				/* There is no page left, but we need to limit
-				 * newex->ec_len.
-				 */
-				newex->ec_len = end - newex->ec_block;
-				goto out;
-			}
-			goto next_page;
-		} else {
-			/*Find contiguous delayed buffers. */
-			if (ret > 0 && pages[0]->index == last_offset)
-				head = page_buffers(pages[0]);
-			bh = head;
-			index = 1;
-			start_index = 0;
+		if (se.len == 0)
+			/* A hole found. */
+			return EXT_CONTINUE;
+
+		if (se.start > newex->ec_block) {
+			/* A hole found. */
+			newex->ec_len = min(se.start - newex->ec_block,
+					    newex->ec_len);
+			return EXT_CONTINUE;
 		}
 
-found_mapped_buffer:
-		if (bh != NULL && buffer_delay(bh)) {
-			/* 1st or contiguous delayed buffer found. */
-			if (!(flags & FIEMAP_EXTENT_DELALLOC)) {
-				/*
-				 * 1st delayed buffer found, record
-				 * the start of extent.
-				 */
-				flags |= FIEMAP_EXTENT_DELALLOC;
-				newex->ec_block = end;
-				logical = (__u64)end << blksize_bits;
-			}
-			/* Find contiguous delayed buffers. */
-			do {
-				if (!buffer_delay(bh))
-					goto found_delayed_extent;
-				bh = bh->b_this_page;
-				end++;
-			} while (bh != head);
-
-			for (; index < ret; index++) {
-				if (!page_has_buffers(pages[index])) {
-					bh = NULL;
-					break;
-				}
-				head = page_buffers(pages[index]);
-				if (!head) {
-					bh = NULL;
-					break;
-				}
-
-				if (pages[index]->index !=
-				    pages[start_index]->index + index
-				    - start_index) {
-					/* Blocks are not contiguous. */
-					bh = NULL;
-					break;
-				}
-				bh = head;
-				do {
-					if (!buffer_delay(bh))
-						/* Delayed-extent ends. */
-						goto found_delayed_extent;
-					bh = bh->b_this_page;
-					end++;
-				} while (bh != head);
-			}
-		} else if (!(flags & FIEMAP_EXTENT_DELALLOC))
-			/* a hole found. */
-			goto out;
-
-found_delayed_extent:
-		newex->ec_len = min(end - newex->ec_block,
-						(ext4_lblk_t)EXT_INIT_MAX_LEN);
-		if (ret == nr_pages && bh != NULL &&
-			newex->ec_len < EXT_INIT_MAX_LEN &&
-			buffer_delay(bh)) {
-			/* Have not collected an extent and continue. */
-			for (index = 0; index < ret; index++)
-				page_cache_release(pages[index]);
-			goto repeat;
-		}
-
-		for (index = 0; index < ret; index++)
-			page_cache_release(pages[index]);
-		kfree(pages);
+		flags |= FIEMAP_EXTENT_DELALLOC;
+		newex->ec_len = se.start + se.len - newex->ec_block;
 	}
 
-	physical = (__u64)newex->ec_start << blksize_bits;
-	length =   (__u64)newex->ec_len << blksize_bits;

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

* [PATCH 6/6] ext4: reimplement ext4_find_delay_alloc_range on status extent tree
  2012-04-18  7:07 [PATCH 0/6] ext4: status extents Allison Henderson
                   ` (4 preceding siblings ...)
  2012-04-18  7:07 ` [PATCH 5/6] ext4: reimplement fiemap on status extent tree Allison Henderson
@ 2012-04-18  7:07 ` Allison Henderson
  2012-04-19  1:56 ` [PATCH 0/6] ext4: status extents Darrick J. Wong
  6 siblings, 0 replies; 8+ messages in thread
From: Allison Henderson @ 2012-04-18  7:07 UTC (permalink / raw)
  To: linux-ext4; +Cc: Allison Henderson, Yongqiang Yang

ext4_find_delay_alloc_range is reimplemented on status extent tree.

Signed-off-by: Yongqiang Yang <xiaoqiangnk@gmail.com>
Signed-off-by: Allison Henderson <achender@linux.vnet.ibm.com>
---
:100644 100644 704021e... 896f2fb... M	fs/ext4/ext4.h
:100644 100644 a52db3a... 14ef9f5... M	fs/ext4/ext4_extents.h
:100644 100644 cee94ce... bfcbde3... M	fs/ext4/extents.c
:100644 100644 adeae2f... 8970254... M	fs/ext4/inode.c
 fs/ext4/ext4.h         |    4 --
 fs/ext4/ext4_extents.h |    3 +-
 fs/ext4/extents.c      |  109 +++++------------------------------------------
 fs/ext4/inode.c        |   53 +-----------------------
 4 files changed, 14 insertions(+), 155 deletions(-)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 704021e..896f2fb 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2304,14 +2304,10 @@ enum ext4_state_bits {
 				 * never, ever appear in a buffer_head's state
 				 * flag. See EXT4_MAP_FROM_CLUSTER to see where
 				 * this is used. */
-	BH_Da_Mapped,	/* Delayed allocated block that now has a mapping. This
-			 * flag is set when ext4_map_blocks is called on a
-			 * delayed allocated block to get its real mapping. */
 };
 
 BUFFER_FNS(Uninit, uninit)
 TAS_BUFFER_FNS(Uninit, uninit)
-BUFFER_FNS(Da_Mapped, da_mapped)
 
 /*
  * Add new method to test wether block and inode bitmaps are properly
diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h
index a52db3a..14ef9f5 100644
--- a/fs/ext4/ext4_extents.h
+++ b/fs/ext4/ext4_extents.h
@@ -290,7 +290,6 @@ extern struct ext4_ext_path *ext4_ext_find_extent(struct inode *, ext4_lblk_t,
 							struct ext4_ext_path *);
 extern void ext4_ext_drop_refs(struct ext4_ext_path *);
 extern int ext4_ext_check_inode(struct inode *inode);
-extern int ext4_find_delalloc_cluster(struct inode *inode, ext4_lblk_t lblk,
-				      int search_hint_reverse);
+extern int ext4_find_delalloc_cluster(struct inode *inode, ext4_lblk_t lblk);
 #endif /* _EXT4_EXTENTS */
 
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index cee94ce..bfcbde3 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -3262,112 +3262,27 @@ static int check_eofblocks_fl(handle_t *handle, struct inode *inode,
 /**
  * ext4_find_delalloc_range: find delayed allocated block in the given range.
  *
- * Goes through the buffer heads in the range [lblk_start, lblk_end] and returns
- * whether there are any buffers marked for delayed allocation. It returns '1'
- * on the first delalloc'ed buffer head found. If no buffer head in the given
- * range is marked for delalloc, it returns 0.
- * lblk_start should always be <= lblk_end.
- * search_hint_reverse is to indicate that searching in reverse from lblk_end to
- * lblk_start might be more efficient (i.e., we will likely hit the delalloc'ed
- * block sooner). This is useful when blocks are truncated sequentially from
- * lblk_start towards lblk_end.
+ * Return 1 if there is a delalloc block in the range, otherwise 0.
  */
 static int ext4_find_delalloc_range(struct inode *inode,
 				    ext4_lblk_t lblk_start,
-				    ext4_lblk_t lblk_end,
-				    int search_hint_reverse)
+				    ext4_lblk_t lblk_end)
 {
-	struct address_space *mapping = inode->i_mapping;
-	struct buffer_head *head, *bh = NULL;
-	struct page *page;
-	ext4_lblk_t i, pg_lblk;
-	pgoff_t index;
-
-	/* reverse search wont work if fs block size is less than page size */
-	if (inode->i_blkbits < PAGE_CACHE_SHIFT)
-		search_hint_reverse = 0;
-
-	if (search_hint_reverse)
-		i = lblk_end;
-	else
-		i = lblk_start;
-
-	index = i >> (PAGE_CACHE_SHIFT - inode->i_blkbits);
-
-	while ((i >= lblk_start) && (i <= lblk_end)) {
-		page = find_get_page(mapping, index);
-		if (!page)
-			goto nextpage;
-
-		if (!page_has_buffers(page))
-			goto nextpage;
-
-		head = page_buffers(page);
-		if (!head)
-			goto nextpage;
-
-		bh = head;
-		pg_lblk = index << (PAGE_CACHE_SHIFT -
-						inode->i_blkbits);
-		do {
-			if (unlikely(pg_lblk < lblk_start)) {
-				/*
-				 * This is possible when fs block size is less
-				 * than page size and our cluster starts/ends in
-				 * middle of the page. So we need to skip the
-				 * initial few blocks till we reach the 'lblk'
-				 */
-				pg_lblk++;
-				continue;
-			}
-
-			/* Check if the buffer is delayed allocated and that it
-			 * is not yet mapped. (when da-buffers are mapped during
-			 * their writeout, their da_mapped bit is set.)
-			 */
-			if (buffer_delay(bh) && !buffer_da_mapped(bh)) {
-				page_cache_release(page);
-				trace_ext4_find_delalloc_range(inode,
-						lblk_start, lblk_end,
-						search_hint_reverse,
-						1, i);
-				return 1;
-			}
-			if (search_hint_reverse)
-				i--;
-			else
-				i++;
-		} while ((i >= lblk_start) && (i <= lblk_end) &&
-				((bh = bh->b_this_page) != head));
-nextpage:
-		if (page)
-			page_cache_release(page);
-		/*
-		 * Move to next page. 'i' will be the first lblk in the next
-		 * page.
-		 */
-		if (search_hint_reverse)
-			index--;
-		else
-			index++;
-		i = index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
-	}
+	struct status_extent se;
 
-	trace_ext4_find_delalloc_range(inode, lblk_start, lblk_end,
-					search_hint_reverse, 0, 0);
-	return 0;
+	se.start = lblk_start;
+	ext4_se_find_extent(inode, &se);
+	return (se.start + se.len) >= lblk_end && se.start <= lblk_start;
 }
 
-int ext4_find_delalloc_cluster(struct inode *inode, ext4_lblk_t lblk,
-			       int search_hint_reverse)
+int ext4_find_delalloc_cluster(struct inode *inode, ext4_lblk_t lblk)
 {
 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
 	ext4_lblk_t lblk_start, lblk_end;
 	lblk_start = lblk & (~(sbi->s_cluster_ratio - 1));
 	lblk_end = lblk_start + sbi->s_cluster_ratio - 1;
 
-	return ext4_find_delalloc_range(inode, lblk_start, lblk_end,
-					search_hint_reverse);
+	return ext4_find_delalloc_range(inode, lblk_start, lblk_end);
 }
 
 /**
@@ -3428,7 +3343,7 @@ get_reserved_cluster_alloc(struct inode *inode, ext4_lblk_t lblk_start,
 		lblk_from = lblk_start & (~(sbi->s_cluster_ratio - 1));
 		lblk_to = lblk_from + c_offset - 1;
 
-		if (ext4_find_delalloc_range(inode, lblk_from, lblk_to, 0))
+		if (ext4_find_delalloc_range(inode, lblk_from, lblk_to))
 			allocated_clusters--;
 	}
 
@@ -3438,7 +3353,7 @@ get_reserved_cluster_alloc(struct inode *inode, ext4_lblk_t lblk_start,
 		lblk_from = lblk_start + num_blks;
 		lblk_to = lblk_from + (sbi->s_cluster_ratio - c_offset) - 1;
 
-		if (ext4_find_delalloc_range(inode, lblk_from, lblk_to, 0))
+		if (ext4_find_delalloc_range(inode, lblk_from, lblk_to))
 			allocated_clusters--;
 	}
 
@@ -3728,7 +3643,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 		ext4_ext_in_cache(inode, map->m_lblk, &newex)) {
 		if (!newex.ee_start_lo && !newex.ee_start_hi) {
 			if ((sbi->s_cluster_ratio > 1) &&
-			    ext4_find_delalloc_cluster(inode, map->m_lblk, 0))
+			    ext4_find_delalloc_cluster(inode, map->m_lblk))
 				map->m_flags |= EXT4_MAP_FROM_CLUSTER;
 
 			if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) {
@@ -3903,7 +3818,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 	}
 
 	if ((sbi->s_cluster_ratio > 1) &&
-	    ext4_find_delalloc_cluster(inode, map->m_lblk, 0))
+	    ext4_find_delalloc_cluster(inode, map->m_lblk))
 		map->m_flags |= EXT4_MAP_FROM_CLUSTER;
 
 	/*
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index adeae2f..8970254 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -398,49 +398,6 @@ static pgoff_t ext4_num_dirty_pages(struct inode *inode, pgoff_t idx,
 }
 
 /*
- * Sets the BH_Da_Mapped bit on the buffer heads corresponding to the given map.
- */
-static void set_buffers_da_mapped(struct inode *inode,
-				   struct ext4_map_blocks *map)
-{
-	struct address_space *mapping = inode->i_mapping;
-	struct pagevec pvec;
-	int i, nr_pages;
-	pgoff_t index, end;
-
-	index = map->m_lblk >> (PAGE_CACHE_SHIFT - inode->i_blkbits);
-	end = (map->m_lblk + map->m_len - 1) >>
-		(PAGE_CACHE_SHIFT - inode->i_blkbits);
-
-	pagevec_init(&pvec, 0);
-	while (index <= end) {
-		nr_pages = pagevec_lookup(&pvec, mapping, index,
-					  min(end - index + 1,
-					      (pgoff_t)PAGEVEC_SIZE));
-		if (nr_pages == 0)
-			break;
-		for (i = 0; i < nr_pages; i++) {
-			struct page *page = pvec.pages[i];
-			struct buffer_head *bh, *head;
-
-			if (unlikely(page->mapping != mapping) ||
-			    !PageDirty(page))
-				break;
-
-			if (page_has_buffers(page)) {
-				bh = head = page_buffers(page);
-				do {
-					set_buffer_da_mapped(bh);
-					bh = bh->b_this_page;
-				} while (bh != head);
-			}
-			index++;
-		}
-		pagevec_release(&pvec);
-	}
-}
-
-/*
  * The ext4_map_blocks() function tries to look up the requested blocks,
  * and returns if the blocks are already mapped.
  *
@@ -571,13 +528,8 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
 	if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) {
 		ext4_clear_inode_state(inode, EXT4_STATE_DELALLOC_RESERVED);
 
-		/* If we have successfully mapped the delayed allocated blocks,
-		 * set the BH_Da_Mapped bit on them. Its important to do this
-		 * under the protection of i_data_sem.
-		 */
 		if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) {
 			int ret;
-			set_buffers_da_mapped(inode, map);
 delayed_mapped:
 			/* delayed allocation blocks has been allocated */
 			ret = ext4_se_remove_space(inode, map->m_lblk,
@@ -1221,7 +1173,6 @@ static void ext4_da_page_release_reservation(struct page *page,
 		if ((offset <= curr_off) && (buffer_delay(bh))) {
 			to_release++;
 			clear_buffer_delay(bh);
-			clear_buffer_da_mapped(bh);
 		}
 		curr_off = next_off;
 	} while ((bh = bh->b_this_page) != head);
@@ -1234,7 +1185,7 @@ static void ext4_da_page_release_reservation(struct page *page,
 		lblk = (page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits)) +
 			((num_clusters - 1) << sbi->s_cluster_bits);
 		if (sbi->s_cluster_ratio == 1 ||
-		    !ext4_find_delalloc_cluster(inode, lblk, 1))
+		    !ext4_find_delalloc_cluster(inode, lblk))
 			ext4_da_release_space(inode, 1);
 
 		num_clusters--;
@@ -1340,8 +1291,6 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd,
 						clear_buffer_delay(bh);
 						bh->b_blocknr = pblock;
 					}
-					if (buffer_da_mapped(bh))
-						clear_buffer_da_mapped(bh);
 					if (buffer_unwritten(bh) ||
 					    buffer_mapped(bh))
 						BUG_ON(bh->b_blocknr != pblock);
-- 
1.7.1


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

* Re: [PATCH 0/6] ext4: status extents
  2012-04-18  7:07 [PATCH 0/6] ext4: status extents Allison Henderson
                   ` (5 preceding siblings ...)
  2012-04-18  7:07 ` [PATCH 6/6] ext4: reimplement ext4_find_delay_alloc_range " Allison Henderson
@ 2012-04-19  1:56 ` Darrick J. Wong
  6 siblings, 0 replies; 8+ messages in thread
From: Darrick J. Wong @ 2012-04-19  1:56 UTC (permalink / raw)
  To: Allison Henderson; +Cc: linux-ext4

On Wed, Apr 18, 2012 at 12:07:12AM -0700, Allison Henderson wrote:
> This set is based on the earlier delayed extent tree, but has
> been renamed to a "status extent" scheme.  The plan is that the
> tree will be expanded to track allocated extents and also
> support extent locks.  Thus status extents seemed like a
> more appropriate name.

How about "extent status tree" ?

> 
> Allison Henderson (6):
>   ext4: add two structures supporting status extent tree
>   ext4: add operations on status extent tree
>   ext4: initialize status extent tree
>   ext4: let ext4 maintian status extent trees

"maintain".

--D

>   ext4: reimplement fiemap on status extent tree
>   ext4: reimplement ext4_find_delay_alloc_range on status extent tree
> 
>  fs/ext4/Makefile         |    2 +-
>  fs/ext4/ext4.h           |    9 +-
>  fs/ext4/ext4_extents.h   |    3 +-
>  fs/ext4/extents.c        |  297 ++++-----------------------------
>  fs/ext4/indirect.c       |    3 +
>  fs/ext4/inode.c          |   83 ++++------
>  fs/ext4/status_extents.c |  417 ++++++++++++++++++++++++++++++++++++++++++++++
>  fs/ext4/status_extents.h |   40 +++++
>  fs/ext4/super.c          |   13 ++-
>  9 files changed, 545 insertions(+), 322 deletions(-)
>  create mode 100644 fs/ext4/status_extents.c
>  create mode 100644 fs/ext4/status_extents.h
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


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

end of thread, other threads:[~2012-04-19  1:57 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-04-18  7:07 [PATCH 0/6] ext4: status extents Allison Henderson
2012-04-18  7:07 ` [PATCH 1/6] ext4: add two structures supporting status extent tree Allison Henderson
2012-04-18  7:07 ` [PATCH 2/6] ext4: add operations on " Allison Henderson
2012-04-18  7:07 ` [PATCH 3/6] ext4: initialize " Allison Henderson
2012-04-18  7:07 ` [PATCH 4/6] ext4: let ext4 maintian status extent trees Allison Henderson
2012-04-18  7:07 ` [PATCH 5/6] ext4: reimplement fiemap on status extent tree Allison Henderson
2012-04-18  7:07 ` [PATCH 6/6] ext4: reimplement ext4_find_delay_alloc_range " Allison Henderson
2012-04-19  1:56 ` [PATCH 0/6] ext4: status extents Darrick J. Wong

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).