linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/10] btrfs: reada: Avoid many times of empty loop
@ 2015-12-31 15:03 Zhao Lei
  2015-12-31 15:03 ` [PATCH 01/10] " Zhao Lei
                   ` (9 more replies)
  0 siblings, 10 replies; 11+ messages in thread
From: Zhao Lei @ 2015-12-31 15:03 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Zhao Lei

This is some cleanup, bugfix and enhance for reada, tested by a
script running scrub and relatice trace log.

Zhao Lei (10):
  btrfs: reada: Avoid many times of empty loop
  btrfs: reada: Move is_need_to_readahead contition earlier
  btrfs: reada: add all reachable mirrors into reada device list
  btrfs: reada: bypass adding extent when all zone failed
  btrfs: reada: Remove level argument in severial functions
  btrfs: reada: move reada_extent_put() to place after
    __readahead_hook()
  btrfs: reada: Pass reada_extent into __readahead_hook() directly
  btrfs: reada: Use fs_info instead of root in __readahead_hook's
    argument
  btrfs: reada: Jump into cleanup in direct way for __readahead_hook()
  btrfs: reada: Fix a debug code typo

 fs/btrfs/ctree.h   |   4 +-
 fs/btrfs/disk-io.c |  22 +++----
 fs/btrfs/reada.c   | 173 ++++++++++++++++++++++++++---------------------------
 3 files changed, 98 insertions(+), 101 deletions(-)

-- 
1.8.5.1




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

* [PATCH 01/10] btrfs: reada: Avoid many times of empty loop
  2015-12-31 15:03 [PATCH 00/10] btrfs: reada: Avoid many times of empty loop Zhao Lei
@ 2015-12-31 15:03 ` Zhao Lei
  2015-12-31 15:03 ` [PATCH 02/10] btrfs: reada: Move is_need_to_readahead contition earlier Zhao Lei
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Zhao Lei @ 2015-12-31 15:03 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Zhao Lei

We can see following loop(10000 times) in trace_log:
 [   75.416137] ZL_DEBUG: reada_start_machine_dev:730: pid=771 comm=kworker/u2:3 re->ref_cnt ffff88003741e0c0 1 -> 2
 [   75.417413] ZL_DEBUG: reada_extent_put:524: pid=771 comm=kworker/u2:3 re = ffff88003741e0c0, refcnt = 2 -> 1
 [   75.418611] ZL_DEBUG: __readahead_hook:129: pid=771 comm=kworker/u2:3 re->ref_cnt ffff88003741e0c0 1 -> 2
 [   75.419793] ZL_DEBUG: reada_extent_put:524: pid=771 comm=kworker/u2:3 re = ffff88003741e0c0, refcnt = 2 -> 1

 [   75.421016] ZL_DEBUG: reada_start_machine_dev:730: pid=771 comm=kworker/u2:3 re->ref_cnt ffff88003741e0c0 1 -> 2
 [   75.422324] ZL_DEBUG: reada_extent_put:524: pid=771 comm=kworker/u2:3 re = ffff88003741e0c0, refcnt = 2 -> 1
 [   75.423661] ZL_DEBUG: __readahead_hook:129: pid=771 comm=kworker/u2:3 re->ref_cnt ffff88003741e0c0 1 -> 2
 [   75.424882] ZL_DEBUG: reada_extent_put:524: pid=771 comm=kworker/u2:3 re = ffff88003741e0c0, refcnt = 2 -> 1

 ...(10000 times)

 [  124.101672] ZL_DEBUG: reada_start_machine_dev:730: pid=771 comm=kworker/u2:3 re->ref_cnt ffff88003741e0c0 1 -> 2
 [  124.102850] ZL_DEBUG: reada_extent_put:524: pid=771 comm=kworker/u2:3 re = ffff88003741e0c0, refcnt = 2 -> 1
 [  124.104008] ZL_DEBUG: __readahead_hook:129: pid=771 comm=kworker/u2:3 re->ref_cnt ffff88003741e0c0 1 -> 2
 [  124.105121] ZL_DEBUG: reada_extent_put:524: pid=771 comm=kworker/u2:3 re = ffff88003741e0c0, refcnt = 2 -> 1

Reason:
 If more than one user trigger reada in same extent, the first task
 finished setting of reada data struct and call reada_start_machine()
 to start, and the second task only add a ref_count but have not
 add reada_extctl struct completely, the reada_extent can not finished
 all jobs, and will be selected in __reada_start_machine() for 10000
 times(total times in __reada_start_machine()).

Fix:
 For a reada_extent without job, we don't need to run it, just return
 0 to let caller break.

Signed-off-by: Zhao Lei <zhaolei@cn.fujitsu.com>
---
 fs/btrfs/reada.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/btrfs/reada.c b/fs/btrfs/reada.c
index c65b42f..fb21bf0 100644
--- a/fs/btrfs/reada.c
+++ b/fs/btrfs/reada.c
@@ -713,7 +713,7 @@ static int reada_start_machine_dev(struct btrfs_fs_info *fs_info,
 	logical = re->logical;
 
 	spin_lock(&re->lock);
-	if (re->scheduled_for == NULL) {
+	if (!re->scheduled_for && !list_empty(&re->extctl)) {
 		re->scheduled_for = dev;
 		need_kick = 1;
 	}
-- 
1.8.5.1




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

* [PATCH 02/10] btrfs: reada: Move is_need_to_readahead contition earlier
  2015-12-31 15:03 [PATCH 00/10] btrfs: reada: Avoid many times of empty loop Zhao Lei
  2015-12-31 15:03 ` [PATCH 01/10] " Zhao Lei
@ 2015-12-31 15:03 ` Zhao Lei
  2015-12-31 15:03 ` [PATCH 03/10] btrfs: reada: add all reachable mirrors into reada device list Zhao Lei
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Zhao Lei @ 2015-12-31 15:03 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Zhao Lei

Move is_need_to_readahead contition earlier to avoid useless loop
to get relative data for readahead.

Signed-off-by: Zhao Lei <zhaolei@cn.fujitsu.com>
---
 fs/btrfs/reada.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/fs/btrfs/reada.c b/fs/btrfs/reada.c
index fb21bf0..dcc5b69 100644
--- a/fs/btrfs/reada.c
+++ b/fs/btrfs/reada.c
@@ -665,7 +665,6 @@ static int reada_start_machine_dev(struct btrfs_fs_info *fs_info,
 	u64 logical;
 	int ret;
 	int i;
-	int need_kick = 0;
 
 	spin_lock(&fs_info->reada_lock);
 	if (dev->reada_curr_zone == NULL) {
@@ -701,6 +700,15 @@ static int reada_start_machine_dev(struct btrfs_fs_info *fs_info,
 
 	spin_unlock(&fs_info->reada_lock);
 
+	spin_lock(&re->lock);
+		if (re->scheduled_for || list_empty(&re->extctl)) {
+			spin_unlock(&re->lock);
+			reada_extent_put(fs_info, re);
+			return 0;
+		}
+		re->scheduled_for = dev;
+	spin_unlock(&re->lock);
+
 	/*
 	 * find mirror num
 	 */
@@ -712,18 +720,8 @@ static int reada_start_machine_dev(struct btrfs_fs_info *fs_info,
 	}
 	logical = re->logical;
 
-	spin_lock(&re->lock);
-	if (!re->scheduled_for && !list_empty(&re->extctl)) {
-		re->scheduled_for = dev;
-		need_kick = 1;
-	}
-	spin_unlock(&re->lock);
-
 	reada_extent_put(fs_info, re);
 
-	if (!need_kick)
-		return 0;
-
 	atomic_inc(&dev->reada_in_flight);
 	ret = reada_tree_block_flagged(fs_info->extent_root, logical,
 			mirror_num, &eb);
-- 
1.8.5.1




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

* [PATCH 03/10] btrfs: reada: add all reachable mirrors into reada device list
  2015-12-31 15:03 [PATCH 00/10] btrfs: reada: Avoid many times of empty loop Zhao Lei
  2015-12-31 15:03 ` [PATCH 01/10] " Zhao Lei
  2015-12-31 15:03 ` [PATCH 02/10] btrfs: reada: Move is_need_to_readahead contition earlier Zhao Lei
@ 2015-12-31 15:03 ` Zhao Lei
  2015-12-31 15:03 ` [PATCH 04/10] btrfs: reada: bypass adding extent when all zone failed Zhao Lei
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Zhao Lei @ 2015-12-31 15:03 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Zhao Lei

If some device is not reachable, we should bypass and continus addingb
next, instead of break on bad device.

Signed-off-by: Zhao Lei <zhaolei@cn.fujitsu.com>
---
 fs/btrfs/reada.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/fs/btrfs/reada.c b/fs/btrfs/reada.c
index dcc5b69..7733a09 100644
--- a/fs/btrfs/reada.c
+++ b/fs/btrfs/reada.c
@@ -328,7 +328,6 @@ static struct reada_extent *reada_find_extent(struct btrfs_root *root,
 	u64 length;
 	int real_stripes;
 	int nzones = 0;
-	int i;
 	unsigned long index = logical >> PAGE_CACHE_SHIFT;
 	int dev_replace_is_ongoing;
 
@@ -380,9 +379,9 @@ static struct reada_extent *reada_find_extent(struct btrfs_root *root,
 		dev = bbio->stripes[nzones].dev;
 		zone = reada_find_zone(fs_info, dev, logical, bbio);
 		if (!zone)
-			break;
+			continue;
 
-		re->zones[nzones] = zone;
+		re->zones[re->nzones++] = zone;
 		spin_lock(&zone->lock);
 		if (!zone->elems)
 			kref_get(&zone->refcnt);
@@ -392,8 +391,7 @@ static struct reada_extent *reada_find_extent(struct btrfs_root *root,
 		kref_put(&zone->refcnt, reada_zone_release);
 		spin_unlock(&fs_info->reada_lock);
 	}
-	re->nzones = nzones;
-	if (nzones == 0) {
+	if (re->nzones == 0) {
 		/* not a single zone found, error and out */
 		goto error;
 	}
@@ -418,8 +416,9 @@ static struct reada_extent *reada_find_extent(struct btrfs_root *root,
 	prev_dev = NULL;
 	dev_replace_is_ongoing = btrfs_dev_replace_is_ongoing(
 			&fs_info->dev_replace);
-	for (i = 0; i < nzones; ++i) {
-		dev = bbio->stripes[i].dev;
+	for (nzones = 0; nzones < re->nzones; ++nzones) {
+		dev = re->zones[nzones]->device;
+
 		if (dev == prev_dev) {
 			/*
 			 * in case of DUP, just add the first zone. As both
@@ -450,8 +449,8 @@ static struct reada_extent *reada_find_extent(struct btrfs_root *root,
 		prev_dev = dev;
 		ret = radix_tree_insert(&dev->reada_extents, index, re);
 		if (ret) {
-			while (--i >= 0) {
-				dev = bbio->stripes[i].dev;
+			while (--nzones >= 0) {
+				dev = re->zones[nzones]->device;
 				BUG_ON(dev == NULL);
 				/* ignore whether the entry was inserted */
 				radix_tree_delete(&dev->reada_extents, index);
@@ -470,10 +469,9 @@ static struct reada_extent *reada_find_extent(struct btrfs_root *root,
 	return re;
 
 error:
-	while (nzones) {
+	for (nzones = 0; nzones < re->nzones; ++nzones) {
 		struct reada_zone *zone;
 
-		--nzones;
 		zone = re->zones[nzones];
 		kref_get(&zone->refcnt);
 		spin_lock(&zone->lock);
-- 
1.8.5.1




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

* [PATCH 04/10] btrfs: reada: bypass adding extent when all zone failed
  2015-12-31 15:03 [PATCH 00/10] btrfs: reada: Avoid many times of empty loop Zhao Lei
                   ` (2 preceding siblings ...)
  2015-12-31 15:03 ` [PATCH 03/10] btrfs: reada: add all reachable mirrors into reada device list Zhao Lei
@ 2015-12-31 15:03 ` Zhao Lei
  2015-12-31 15:03 ` [PATCH 05/10] btrfs: reada: Remove level argument in severial functions Zhao Lei
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Zhao Lei @ 2015-12-31 15:03 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Zhao Lei

When failed adding all dev_zones for a reada_extent, the extent
will have no chance to be selected to run, and keep in memory
for ever.

We should bypass this extent to avoid above case.

Signed-off-by: Zhao Lei <zhaolei@cn.fujitsu.com>
---
 fs/btrfs/reada.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/fs/btrfs/reada.c b/fs/btrfs/reada.c
index 7733a09..ef9457e 100644
--- a/fs/btrfs/reada.c
+++ b/fs/btrfs/reada.c
@@ -330,6 +330,7 @@ static struct reada_extent *reada_find_extent(struct btrfs_root *root,
 	int nzones = 0;
 	unsigned long index = logical >> PAGE_CACHE_SHIFT;
 	int dev_replace_is_ongoing;
+	int have_zone = 0;
 
 	spin_lock(&fs_info->reada_lock);
 	re = radix_tree_lookup(&fs_info->reada_tree, index);
@@ -461,10 +462,14 @@ static struct reada_extent *reada_find_extent(struct btrfs_root *root,
 			btrfs_dev_replace_unlock(&fs_info->dev_replace);
 			goto error;
 		}
+		have_zone = 1;
 	}
 	spin_unlock(&fs_info->reada_lock);
 	btrfs_dev_replace_unlock(&fs_info->dev_replace);
 
+	if (!have_zone)
+		goto error;
+
 	btrfs_put_bbio(bbio);
 	return re;
 
-- 
1.8.5.1




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

* [PATCH 05/10] btrfs: reada: Remove level argument in severial functions
  2015-12-31 15:03 [PATCH 00/10] btrfs: reada: Avoid many times of empty loop Zhao Lei
                   ` (3 preceding siblings ...)
  2015-12-31 15:03 ` [PATCH 04/10] btrfs: reada: bypass adding extent when all zone failed Zhao Lei
@ 2015-12-31 15:03 ` Zhao Lei
  2015-12-31 15:03 ` [PATCH 06/10] btrfs: reada: move reada_extent_put to place after __readahead_hook() Zhao Lei
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Zhao Lei @ 2015-12-31 15:03 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Zhao Lei

level is not used in severial functions, remove them from arguments,
and remove relative code for get its value.

Signed-off-by: Zhao Lei <zhaolei@cn.fujitsu.com>
---
 fs/btrfs/reada.c | 15 ++++++---------
 1 file changed, 6 insertions(+), 9 deletions(-)

diff --git a/fs/btrfs/reada.c b/fs/btrfs/reada.c
index ef9457e..66409f3 100644
--- a/fs/btrfs/reada.c
+++ b/fs/btrfs/reada.c
@@ -101,7 +101,7 @@ static void reada_start_machine(struct btrfs_fs_info *fs_info);
 static void __reada_start_machine(struct btrfs_fs_info *fs_info);
 
 static int reada_add_block(struct reada_control *rc, u64 logical,
-			   struct btrfs_key *top, int level, u64 generation);
+			   struct btrfs_key *top, u64 generation);
 
 /* recurses */
 /* in case of err, eb might be NULL */
@@ -197,8 +197,7 @@ static int __readahead_hook(struct btrfs_root *root, struct extent_buffer *eb,
 			if (rec->generation == generation &&
 			    btrfs_comp_cpu_keys(&key, &rc->key_end) < 0 &&
 			    btrfs_comp_cpu_keys(&next_key, &rc->key_start) > 0)
-				reada_add_block(rc, bytenr, &next_key,
-						level - 1, n_gen);
+				reada_add_block(rc, bytenr, &next_key, n_gen);
 		}
 	}
 	/*
@@ -315,7 +314,7 @@ static struct reada_zone *reada_find_zone(struct btrfs_fs_info *fs_info,
 
 static struct reada_extent *reada_find_extent(struct btrfs_root *root,
 					      u64 logical,
-					      struct btrfs_key *top, int level)
+					      struct btrfs_key *top)
 {
 	int ret;
 	struct reada_extent *re = NULL;
@@ -562,13 +561,13 @@ static void reada_control_release(struct kref *kref)
 }
 
 static int reada_add_block(struct reada_control *rc, u64 logical,
-			   struct btrfs_key *top, int level, u64 generation)
+			   struct btrfs_key *top, u64 generation)
 {
 	struct btrfs_root *root = rc->root;
 	struct reada_extent *re;
 	struct reada_extctl *rec;
 
-	re = reada_find_extent(root, logical, top, level); /* takes one ref */
+	re = reada_find_extent(root, logical, top); /* takes one ref */
 	if (!re)
 		return -1;
 
@@ -921,7 +920,6 @@ struct reada_control *btrfs_reada_add(struct btrfs_root *root,
 	struct reada_control *rc;
 	u64 start;
 	u64 generation;
-	int level;
 	int ret;
 	struct extent_buffer *node;
 	static struct btrfs_key max_key = {
@@ -944,11 +942,10 @@ struct reada_control *btrfs_reada_add(struct btrfs_root *root,
 
 	node = btrfs_root_node(root);
 	start = node->start;
-	level = btrfs_header_level(node);
 	generation = btrfs_header_generation(node);
 	free_extent_buffer(node);
 
-	ret = reada_add_block(rc, start, &max_key, level, generation);
+	ret = reada_add_block(rc, start, &max_key, generation);
 	if (ret) {
 		kfree(rc);
 		return ERR_PTR(ret);
-- 
1.8.5.1




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

* [PATCH 06/10] btrfs: reada: move reada_extent_put to place after __readahead_hook()
  2015-12-31 15:03 [PATCH 00/10] btrfs: reada: Avoid many times of empty loop Zhao Lei
                   ` (4 preceding siblings ...)
  2015-12-31 15:03 ` [PATCH 05/10] btrfs: reada: Remove level argument in severial functions Zhao Lei
@ 2015-12-31 15:03 ` Zhao Lei
  2015-12-31 15:03 ` [PATCH 07/10] btrfs: reada: Pass reada_extent into __readahead_hook directly Zhao Lei
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Zhao Lei @ 2015-12-31 15:03 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Zhao Lei

We can't release reada_extent earlier than __readahead_hook(), because
__readahead_hook() still need to use it, it is necessary to hode a refcnt
to avoid it be freed.

Actually it is not a problem after my patch named:
  Avoid many times of empty loop
It make reada_extent in above line include at least one reada_extctl,
which keeps additional one refcnt for reada_extent.

But we still need this patch to make the code in pretty logic.

Signed-off-by: Zhao Lei <zhaolei@cn.fujitsu.com>
---
 fs/btrfs/reada.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/btrfs/reada.c b/fs/btrfs/reada.c
index 66409f3..7015906 100644
--- a/fs/btrfs/reada.c
+++ b/fs/btrfs/reada.c
@@ -722,8 +722,6 @@ static int reada_start_machine_dev(struct btrfs_fs_info *fs_info,
 	}
 	logical = re->logical;
 
-	reada_extent_put(fs_info, re);
-
 	atomic_inc(&dev->reada_in_flight);
 	ret = reada_tree_block_flagged(fs_info->extent_root, logical,
 			mirror_num, &eb);
@@ -735,6 +733,8 @@ static int reada_start_machine_dev(struct btrfs_fs_info *fs_info,
 	if (eb)
 		free_extent_buffer(eb);
 
+	reada_extent_put(fs_info, re);
+
 	return 1;
 
 }
-- 
1.8.5.1




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

* [PATCH 07/10] btrfs: reada: Pass reada_extent into __readahead_hook directly
  2015-12-31 15:03 [PATCH 00/10] btrfs: reada: Avoid many times of empty loop Zhao Lei
                   ` (5 preceding siblings ...)
  2015-12-31 15:03 ` [PATCH 06/10] btrfs: reada: move reada_extent_put to place after __readahead_hook() Zhao Lei
@ 2015-12-31 15:03 ` Zhao Lei
  2015-12-31 15:03 ` [PATCH 08/10] btrfs: reada: Use fs_info instead of root in __readahead_hook's argument Zhao Lei
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Zhao Lei @ 2015-12-31 15:03 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Zhao Lei

reada_start_machine_dev() already have reada_extent pointer, pass
it into __readahead_hook() directly instead of search radix_tree
will make code run faster.

Signed-off-by: Zhao Lei <zhaolei@cn.fujitsu.com>
---
 fs/btrfs/reada.c | 45 ++++++++++++++++++++++++---------------------
 1 file changed, 24 insertions(+), 21 deletions(-)

diff --git a/fs/btrfs/reada.c b/fs/btrfs/reada.c
index 7015906..7668066 100644
--- a/fs/btrfs/reada.c
+++ b/fs/btrfs/reada.c
@@ -105,33 +105,21 @@ static int reada_add_block(struct reada_control *rc, u64 logical,
 
 /* recurses */
 /* in case of err, eb might be NULL */
-static int __readahead_hook(struct btrfs_root *root, struct extent_buffer *eb,
-			    u64 start, int err)
+static void __readahead_hook(struct btrfs_root *root, struct reada_extent *re,
+			     struct extent_buffer *eb, u64 start, int err)
 {
 	int level = 0;
 	int nritems;
 	int i;
 	u64 bytenr;
 	u64 generation;
-	struct reada_extent *re;
 	struct btrfs_fs_info *fs_info = root->fs_info;
 	struct list_head list;
-	unsigned long index = start >> PAGE_CACHE_SHIFT;
 	struct btrfs_device *for_dev;
 
 	if (eb)
 		level = btrfs_header_level(eb);
 
-	/* find extent */
-	spin_lock(&fs_info->reada_lock);
-	re = radix_tree_lookup(&fs_info->reada_tree, index);
-	if (re)
-		re->refcnt++;
-	spin_unlock(&fs_info->reada_lock);
-
-	if (!re)
-		return -1;
-
 	spin_lock(&re->lock);
 	/*
 	 * just take the full list from the extent. afterwards we
@@ -221,11 +209,11 @@ static int __readahead_hook(struct btrfs_root *root, struct extent_buffer *eb,
 
 		reada_extent_put(fs_info, re);	/* one ref for each entry */
 	}
-	reada_extent_put(fs_info, re);	/* our ref */
+
 	if (for_dev)
 		atomic_dec(&for_dev->reada_in_flight);
 
-	return 0;
+	return;
 }
 
 /*
@@ -235,12 +223,27 @@ static int __readahead_hook(struct btrfs_root *root, struct extent_buffer *eb,
 int btree_readahead_hook(struct btrfs_root *root, struct extent_buffer *eb,
 			 u64 start, int err)
 {
-	int ret;
+	int ret = 0;
+	struct reada_extent *re;
+	struct btrfs_fs_info *fs_info = root->fs_info;
 
-	ret = __readahead_hook(root, eb, start, err);
+	/* find extent */
+	spin_lock(&fs_info->reada_lock);
+	re = radix_tree_lookup(&fs_info->reada_tree,
+			       start >> PAGE_CACHE_SHIFT);
+	if (re)
+		re->refcnt++;
+	spin_unlock(&fs_info->reada_lock);
+	if (!re) {
+		ret = -1;
+		goto start_machine;
+	}
 
-	reada_start_machine(root->fs_info);
+	__readahead_hook(fs_info, re, eb, start, err);
+	reada_extent_put(fs_info, re);	/* our ref */
 
+start_machine:
+	reada_start_machine(fs_info);
 	return ret;
 }
 
@@ -726,9 +729,9 @@ static int reada_start_machine_dev(struct btrfs_fs_info *fs_info,
 	ret = reada_tree_block_flagged(fs_info->extent_root, logical,
 			mirror_num, &eb);
 	if (ret)
-		__readahead_hook(fs_info->extent_root, NULL, logical, ret);
+		__readahead_hook(fs_info->extent_root, re, NULL, logical, ret);
 	else if (eb)
-		__readahead_hook(fs_info->extent_root, eb, eb->start, ret);
+		__readahead_hook(fs_info->extent_root, re, eb, eb->start, ret);
 
 	if (eb)
 		free_extent_buffer(eb);
-- 
1.8.5.1




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

* [PATCH 08/10] btrfs: reada: Use fs_info instead of root in __readahead_hook's argument
  2015-12-31 15:03 [PATCH 00/10] btrfs: reada: Avoid many times of empty loop Zhao Lei
                   ` (6 preceding siblings ...)
  2015-12-31 15:03 ` [PATCH 07/10] btrfs: reada: Pass reada_extent into __readahead_hook directly Zhao Lei
@ 2015-12-31 15:03 ` Zhao Lei
  2015-12-31 15:03 ` [PATCH 09/10] btrfs: reada: Jump into cleanup in direct way for __readahead_hook() Zhao Lei
  2015-12-31 15:03 ` [PATCH 10/10] btrfs: reada: Fix a debug code typo Zhao Lei
  9 siblings, 0 replies; 11+ messages in thread
From: Zhao Lei @ 2015-12-31 15:03 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Zhao Lei

What __readahead_hook() need exactly is fs_info, no need to convert
fs_info to root in caller and convert back in __readahead_hook()

Signed-off-by: Zhao Lei <zhaolei@cn.fujitsu.com>
---
 fs/btrfs/ctree.h   |  4 ++--
 fs/btrfs/disk-io.c | 22 +++++++++++-----------
 fs/btrfs/reada.c   | 23 +++++++++++------------
 3 files changed, 24 insertions(+), 25 deletions(-)

diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 54e7b0d..0912f89 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -4358,8 +4358,8 @@ struct reada_control *btrfs_reada_add(struct btrfs_root *root,
 			      struct btrfs_key *start, struct btrfs_key *end);
 int btrfs_reada_wait(void *handle);
 void btrfs_reada_detach(void *handle);
-int btree_readahead_hook(struct btrfs_root *root, struct extent_buffer *eb,
-			 u64 start, int err);
+int btree_readahead_hook(struct btrfs_fs_info *fs_info,
+			 struct extent_buffer *eb, u64 start, int err);
 
 static inline int is_fstree(u64 rootid)
 {
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 974be09..9d120e4 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -604,6 +604,7 @@ static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
 	int found_level;
 	struct extent_buffer *eb;
 	struct btrfs_root *root = BTRFS_I(page->mapping->host)->root;
+	struct btrfs_fs_info *fs_info = root->fs_info;
 	int ret = 0;
 	int reads_done;
 
@@ -629,21 +630,21 @@ static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
 
 	found_start = btrfs_header_bytenr(eb);
 	if (found_start != eb->start) {
-		btrfs_err_rl(eb->fs_info, "bad tree block start %llu %llu",
-			       found_start, eb->start);
+		btrfs_err_rl(fs_info, "bad tree block start %llu %llu",
+			     found_start, eb->start);
 		ret = -EIO;
 		goto err;
 	}
-	if (check_tree_block_fsid(root->fs_info, eb)) {
-		btrfs_err_rl(eb->fs_info, "bad fsid on block %llu",
-			       eb->start);
+	if (check_tree_block_fsid(fs_info, eb)) {
+		btrfs_err_rl(fs_info, "bad fsid on block %llu",
+			     eb->start);
 		ret = -EIO;
 		goto err;
 	}
 	found_level = btrfs_header_level(eb);
 	if (found_level >= BTRFS_MAX_LEVEL) {
-		btrfs_err(root->fs_info, "bad tree block level %d",
-			   (int)btrfs_header_level(eb));
+		btrfs_err(fs_info, "bad tree block level %d",
+			  (int)btrfs_header_level(eb));
 		ret = -EIO;
 		goto err;
 	}
@@ -651,7 +652,7 @@ static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
 	btrfs_set_buffer_lockdep_class(btrfs_header_owner(eb),
 				       eb, found_level);
 
-	ret = csum_tree_block(root->fs_info, eb, 1);
+	ret = csum_tree_block(fs_info, eb, 1);
 	if (ret) {
 		ret = -EIO;
 		goto err;
@@ -672,7 +673,7 @@ static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
 err:
 	if (reads_done &&
 	    test_and_clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags))
-		btree_readahead_hook(root, eb, eb->start, ret);
+		btree_readahead_hook(fs_info, eb, eb->start, ret);
 
 	if (ret) {
 		/*
@@ -691,14 +692,13 @@ out:
 static int btree_io_failed_hook(struct page *page, int failed_mirror)
 {
 	struct extent_buffer *eb;
-	struct btrfs_root *root = BTRFS_I(page->mapping->host)->root;
 
 	eb = (struct extent_buffer *)page->private;
 	set_bit(EXTENT_BUFFER_READ_ERR, &eb->bflags);
 	eb->read_mirror = failed_mirror;
 	atomic_dec(&eb->io_pages);
 	if (test_and_clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags))
-		btree_readahead_hook(root, eb, eb->start, -EIO);
+		btree_readahead_hook(eb->fs_info, eb, eb->start, -EIO);
 	return -EIO;	/* we fixed nothing */
 }
 
diff --git a/fs/btrfs/reada.c b/fs/btrfs/reada.c
index 7668066..869bb1c 100644
--- a/fs/btrfs/reada.c
+++ b/fs/btrfs/reada.c
@@ -105,15 +105,15 @@ static int reada_add_block(struct reada_control *rc, u64 logical,
 
 /* recurses */
 /* in case of err, eb might be NULL */
-static void __readahead_hook(struct btrfs_root *root, struct reada_extent *re,
-			     struct extent_buffer *eb, u64 start, int err)
+static void __readahead_hook(struct btrfs_fs_info *fs_info,
+			     struct reada_extent *re, struct extent_buffer *eb,
+			     u64 start, int err)
 {
 	int level = 0;
 	int nritems;
 	int i;
 	u64 bytenr;
 	u64 generation;
-	struct btrfs_fs_info *fs_info = root->fs_info;
 	struct list_head list;
 	struct btrfs_device *for_dev;
 
@@ -176,10 +176,10 @@ static void __readahead_hook(struct btrfs_root *root, struct reada_extent *re,
 			 */
 #ifdef DEBUG
 			if (rec->generation != generation) {
-				btrfs_debug(root->fs_info,
-					   "generation mismatch for (%llu,%d,%llu) %llu != %llu",
-				       key.objectid, key.type, key.offset,
-				       rec->generation, generation);
+				btrfs_debug(fs_info,
+					    "generation mismatch for (%llu,%d,%llu) %llu != %llu",
+					    key.objectid, key.type, key.offset,
+					    rec->generation, generation);
 			}
 #endif
 			if (rec->generation == generation &&
@@ -220,12 +220,11 @@ static void __readahead_hook(struct btrfs_root *root, struct reada_extent *re,
  * start is passed separately in case eb in NULL, which may be the case with
  * failed I/O
  */
-int btree_readahead_hook(struct btrfs_root *root, struct extent_buffer *eb,
-			 u64 start, int err)
+int btree_readahead_hook(struct btrfs_fs_info *fs_info,
+			 struct extent_buffer *eb, u64 start, int err)
 {
 	int ret = 0;
 	struct reada_extent *re;
-	struct btrfs_fs_info *fs_info = root->fs_info;
 
 	/* find extent */
 	spin_lock(&fs_info->reada_lock);
@@ -729,9 +728,9 @@ static int reada_start_machine_dev(struct btrfs_fs_info *fs_info,
 	ret = reada_tree_block_flagged(fs_info->extent_root, logical,
 			mirror_num, &eb);
 	if (ret)
-		__readahead_hook(fs_info->extent_root, re, NULL, logical, ret);
+		__readahead_hook(fs_info, re, NULL, logical, ret);
 	else if (eb)
-		__readahead_hook(fs_info->extent_root, re, eb, eb->start, ret);
+		__readahead_hook(fs_info, re, eb, eb->start, ret);
 
 	if (eb)
 		free_extent_buffer(eb);
-- 
1.8.5.1




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

* [PATCH 09/10] btrfs: reada: Jump into cleanup in direct way for __readahead_hook()
  2015-12-31 15:03 [PATCH 00/10] btrfs: reada: Avoid many times of empty loop Zhao Lei
                   ` (7 preceding siblings ...)
  2015-12-31 15:03 ` [PATCH 08/10] btrfs: reada: Use fs_info instead of root in __readahead_hook's argument Zhao Lei
@ 2015-12-31 15:03 ` Zhao Lei
  2015-12-31 15:03 ` [PATCH 10/10] btrfs: reada: Fix a debug code typo Zhao Lei
  9 siblings, 0 replies; 11+ messages in thread
From: Zhao Lei @ 2015-12-31 15:03 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Zhao Lei

Current code set nritems to 0 to make for_loop useless to bypass it,
and set generation's value which is not necessary.
Jump into cleanup directly is better choise.

Signed-off-by: Zhao Lei <zhaolei@cn.fujitsu.com>
---
 fs/btrfs/reada.c | 40 +++++++++++++++++++++-------------------
 1 file changed, 21 insertions(+), 19 deletions(-)

diff --git a/fs/btrfs/reada.c b/fs/btrfs/reada.c
index 869bb1c..902f899 100644
--- a/fs/btrfs/reada.c
+++ b/fs/btrfs/reada.c
@@ -130,26 +130,26 @@ static void __readahead_hook(struct btrfs_fs_info *fs_info,
 	re->scheduled_for = NULL;
 	spin_unlock(&re->lock);
 
-	if (err == 0) {
-		nritems = level ? btrfs_header_nritems(eb) : 0;
-		generation = btrfs_header_generation(eb);
-		/*
-		 * FIXME: currently we just set nritems to 0 if this is a leaf,
-		 * effectively ignoring the content. In a next step we could
-		 * trigger more readahead depending from the content, e.g.
-		 * fetch the checksums for the extents in the leaf.
-		 */
-	} else {
-		/*
-		 * this is the error case, the extent buffer has not been
-		 * read correctly. We won't access anything from it and
-		 * just cleanup our data structures. Effectively this will
-		 * cut the branch below this node from read ahead.
-		 */
-		nritems = 0;
-		generation = 0;
-	}
+	/*
+	 * this is the error case, the extent buffer has not been
+	 * read correctly. We won't access anything from it and
+	 * just cleanup our data structures. Effectively this will
+	 * cut the branch below this node from read ahead.
+	 */
+	if (err)
+		goto cleanup;
 
+	/*
+	 * FIXME: currently we just set nritems to 0 if this is a leaf,
+	 * effectively ignoring the content. In a next step we could
+	 * trigger more readahead depending from the content, e.g.
+	 * fetch the checksums for the extents in the leaf.
+	 */
+	if (!level)
+		goto cleanup;
+
+	nritems = btrfs_header_nritems(eb);
+	generation = btrfs_header_generation(eb);
 	for (i = 0; i < nritems; i++) {
 		struct reada_extctl *rec;
 		u64 n_gen;
@@ -188,6 +188,8 @@ static void __readahead_hook(struct btrfs_fs_info *fs_info,
 				reada_add_block(rc, bytenr, &next_key, n_gen);
 		}
 	}
+
+cleanup:
 	/*
 	 * free extctl records
 	 */
-- 
1.8.5.1




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

* [PATCH 10/10] btrfs: reada: Fix a debug code typo
  2015-12-31 15:03 [PATCH 00/10] btrfs: reada: Avoid many times of empty loop Zhao Lei
                   ` (8 preceding siblings ...)
  2015-12-31 15:03 ` [PATCH 09/10] btrfs: reada: Jump into cleanup in direct way for __readahead_hook() Zhao Lei
@ 2015-12-31 15:03 ` Zhao Lei
  9 siblings, 0 replies; 11+ messages in thread
From: Zhao Lei @ 2015-12-31 15:03 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Zhao Lei

Remove one copy of loop to fix the typo of iterate zones.

Signed-off-by: Zhao Lei <zhaolei@cn.fujitsu.com>
---
 fs/btrfs/reada.c | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/fs/btrfs/reada.c b/fs/btrfs/reada.c
index 902f899..53ee7b1 100644
--- a/fs/btrfs/reada.c
+++ b/fs/btrfs/reada.c
@@ -898,14 +898,9 @@ static void dump_devs(struct btrfs_fs_info *fs_info, int all)
 			printk(KERN_CONT " zone %llu-%llu devs",
 				re->zones[i]->start,
 				re->zones[i]->end);
-			for (i = 0; i < re->nzones; ++i) {
-				printk(KERN_CONT " zone %llu-%llu devs",
-					re->zones[i]->start,
-					re->zones[i]->end);
-				for (j = 0; j < re->zones[i]->ndevs; ++j) {
-					printk(KERN_CONT " %lld",
-						re->zones[i]->devs[j]->devid);
-				}
+			for (j = 0; j < re->zones[i]->ndevs; ++j) {
+				printk(KERN_CONT " %lld",
+				       re->zones[i]->devs[j]->devid);
 			}
 		}
 		printk(KERN_CONT "\n");
-- 
1.8.5.1




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

end of thread, other threads:[~2015-12-31 15:08 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-12-31 15:03 [PATCH 00/10] btrfs: reada: Avoid many times of empty loop Zhao Lei
2015-12-31 15:03 ` [PATCH 01/10] " Zhao Lei
2015-12-31 15:03 ` [PATCH 02/10] btrfs: reada: Move is_need_to_readahead contition earlier Zhao Lei
2015-12-31 15:03 ` [PATCH 03/10] btrfs: reada: add all reachable mirrors into reada device list Zhao Lei
2015-12-31 15:03 ` [PATCH 04/10] btrfs: reada: bypass adding extent when all zone failed Zhao Lei
2015-12-31 15:03 ` [PATCH 05/10] btrfs: reada: Remove level argument in severial functions Zhao Lei
2015-12-31 15:03 ` [PATCH 06/10] btrfs: reada: move reada_extent_put to place after __readahead_hook() Zhao Lei
2015-12-31 15:03 ` [PATCH 07/10] btrfs: reada: Pass reada_extent into __readahead_hook directly Zhao Lei
2015-12-31 15:03 ` [PATCH 08/10] btrfs: reada: Use fs_info instead of root in __readahead_hook's argument Zhao Lei
2015-12-31 15:03 ` [PATCH 09/10] btrfs: reada: Jump into cleanup in direct way for __readahead_hook() Zhao Lei
2015-12-31 15:03 ` [PATCH 10/10] btrfs: reada: Fix a debug code typo Zhao Lei

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