Jiri Slaby 8cebe2
From: Qu Wenruo <quwenruo@cn.fujitsu.com>
Jiri Slaby 8cebe2
Date: Thu, 22 Jun 2017 10:01:21 +0800
Jiri Slaby 8cebe2
Subject: [PATCH] btrfs: Remove false alert when fiemap range is smaller than
Jiri Slaby 8cebe2
 on-disk extent
Jiri Slaby 8cebe2
MIME-Version: 1.0
Jiri Slaby 8cebe2
Content-Type: text/plain; charset=UTF-8
Jiri Slaby 8cebe2
Content-Transfer-Encoding: 8bit
Jiri Slaby 8cebe2
References: bnc#1060662
Jiri Slaby 8cebe2
Patch-mainline: 4.12.7
Jiri Slaby 8cebe2
Git-commit: 848c23b78fafdcd3270b06a30737f8dbd70c347f
Jiri Slaby 8cebe2
Jiri Slaby 8cebe2
commit 848c23b78fafdcd3270b06a30737f8dbd70c347f upstream.
Jiri Slaby 8cebe2
Jiri Slaby 8cebe2
Commit 4751832da990 ("btrfs: fiemap: Cache and merge fiemap extent before
Jiri Slaby 8cebe2
submit it to user") introduced a warning to catch unemitted cached
Jiri Slaby 8cebe2
fiemap extent.
Jiri Slaby 8cebe2
Jiri Slaby 8cebe2
However such warning doesn't take the following case into consideration:
Jiri Slaby 8cebe2
Jiri Slaby 8cebe2
0			4K			8K
Jiri Slaby 8cebe2
|<---- fiemap range --->|
Jiri Slaby 8cebe2
|<----------- On-disk extent ------------------>|
Jiri Slaby 8cebe2
Jiri Slaby 8cebe2
In this case, the whole 0~8K is cached, and since it's larger than
Jiri Slaby 8cebe2
fiemap range, it break the fiemap extent emit loop.
Jiri Slaby 8cebe2
This leaves the fiemap extent cached but not emitted, and caught by the
Jiri Slaby 8cebe2
final fiemap extent sanity check, causing kernel warning.
Jiri Slaby 8cebe2
Jiri Slaby 8cebe2
This patch removes the kernel warning and renames the sanity check to
Jiri Slaby 8cebe2
emit_last_fiemap_cache() since it's possible and valid to have cached
Jiri Slaby 8cebe2
fiemap extent.
Jiri Slaby 8cebe2
Jiri Slaby 8cebe2
Reported-by: David Sterba <dsterba@suse.cz>
Jiri Slaby 8cebe2
Reported-by: Adam Borowski <kilobyte@angband.pl>
Jiri Slaby 8cebe2
Fixes: 4751832da990 ("btrfs: fiemap: Cache and merge fiemap extent ...")
Jiri Slaby 8cebe2
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Jiri Slaby 8cebe2
Signed-off-by: David Sterba <dsterba@suse.com>
Jiri Slaby 8cebe2
Cc: Holger Hoffstätte <holger@applied-asynchrony.com>
Jiri Slaby 8cebe2
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Jiri Slaby 8cebe2
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Jiri Slaby 8cebe2
---
Jiri Slaby 8cebe2
 fs/btrfs/extent_io.c | 28 ++++++++++++----------------
Jiri Slaby 8cebe2
 1 file changed, 12 insertions(+), 16 deletions(-)
Jiri Slaby 8cebe2
Jiri Slaby 8cebe2
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
Jiri Slaby 8cebe2
index 3ef90e91d8be..0c7b61f72478 100644
Jiri Slaby 8cebe2
--- a/fs/btrfs/extent_io.c
Jiri Slaby 8cebe2
+++ b/fs/btrfs/extent_io.c
Jiri Slaby 8cebe2
@@ -4463,29 +4463,25 @@ try_submit_last:
Jiri Slaby 8cebe2
 }
Jiri Slaby 8cebe2
 
Jiri Slaby 8cebe2
 /*
Jiri Slaby 8cebe2
- * Sanity check for fiemap cache
Jiri Slaby 8cebe2
+ * Emit last fiemap cache
Jiri Slaby 8cebe2
  *
Jiri Slaby 8cebe2
- * All fiemap cache should be submitted by emit_fiemap_extent()
Jiri Slaby 8cebe2
- * Iteration should be terminated either by last fiemap extent or
Jiri Slaby 8cebe2
- * fieinfo->fi_extents_max.
Jiri Slaby 8cebe2
- * So no cached fiemap should exist.
Jiri Slaby 8cebe2
+ * The last fiemap cache may still be cached in the following case:
Jiri Slaby 8cebe2
+ * 0		      4k		    8k
Jiri Slaby 8cebe2
+ * |<- Fiemap range ->|
Jiri Slaby 8cebe2
+ * |<------------  First extent ----------->|
Jiri Slaby 8cebe2
+ *
Jiri Slaby 8cebe2
+ * In this case, the first extent range will be cached but not emitted.
Jiri Slaby 8cebe2
+ * So we must emit it before ending extent_fiemap().
Jiri Slaby 8cebe2
  */
Jiri Slaby 8cebe2
-static int check_fiemap_cache(struct btrfs_fs_info *fs_info,
Jiri Slaby 8cebe2
-			       struct fiemap_extent_info *fieinfo,
Jiri Slaby 8cebe2
-			       struct fiemap_cache *cache)
Jiri Slaby 8cebe2
+static int emit_last_fiemap_cache(struct btrfs_fs_info *fs_info,
Jiri Slaby 8cebe2
+				  struct fiemap_extent_info *fieinfo,
Jiri Slaby 8cebe2
+				  struct fiemap_cache *cache)
Jiri Slaby 8cebe2
 {
Jiri Slaby 8cebe2
 	int ret;
Jiri Slaby 8cebe2
 
Jiri Slaby 8cebe2
 	if (!cache->cached)
Jiri Slaby 8cebe2
 		return 0;
Jiri Slaby 8cebe2
 
Jiri Slaby 8cebe2
-	/* Small and recoverbale problem, only to info developer */
Jiri Slaby 8cebe2
-#ifdef CONFIG_BTRFS_DEBUG
Jiri Slaby 8cebe2
-	WARN_ON(1);
Jiri Slaby 8cebe2
-#endif
Jiri Slaby 8cebe2
-	btrfs_warn(fs_info,
Jiri Slaby 8cebe2
-		   "unhandled fiemap cache detected: offset=%llu phys=%llu len=%llu flags=0x%x",
Jiri Slaby 8cebe2
-		   cache->offset, cache->phys, cache->len, cache->flags);
Jiri Slaby 8cebe2
 	ret = fiemap_fill_next_extent(fieinfo, cache->offset, cache->phys,
Jiri Slaby 8cebe2
 				      cache->len, cache->flags);
Jiri Slaby 8cebe2
 	cache->cached = false;
Jiri Slaby 8cebe2
@@ -4701,7 +4697,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
Jiri Slaby 8cebe2
 	}
Jiri Slaby 8cebe2
 out_free:
Jiri Slaby 8cebe2
 	if (!ret)
Jiri Slaby 8cebe2
-		ret = check_fiemap_cache(root->fs_info, fieinfo, &cache);
Jiri Slaby 8cebe2
+		ret = emit_last_fiemap_cache(root->fs_info, fieinfo, &cache);
Jiri Slaby 8cebe2
 	free_extent_map(em);
Jiri Slaby 8cebe2
 out:
Jiri Slaby 8cebe2
 	btrfs_free_path(path);
Jiri Slaby 8cebe2
-- 
Jiri Slaby 8cebe2
2.14.2
Jiri Slaby 8cebe2