[Devel] [PATCH rh7 18/38] ploop: bug on bad fiemap (v2)

Andrey Smetanin asmetanin at virtuozzo.com
Fri May 15 09:48:19 PDT 2015


Based on crash analysis, one of extents from ploop em-tree is bad:

ffff883fe6230ae0
  start = 19380224
  end = 19447808
  block_start = 0
  refs = {
    counter = 1
  }

ploop never calculates em->block_start other than by direct assigning:

> em->block_start = fi_extent.fe_physical >> 9;

The patch attempts to catch erroneous (zero) output immediately after
fiemap call.

Changed in v2:
 - WARN_ON (instead of BUG_ON) for delalloc extents

https://jira.sw.ru/browse/PSBM-26762

Signed-off-by: Maxim Patlasov <MPatlasov at parallels.com>
---
 drivers/block/ploop/io_direct_map.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/drivers/block/ploop/io_direct_map.c b/drivers/block/ploop/io_direct_map.c
index b3cb04d..b9a0ce9 100644
--- a/drivers/block/ploop/io_direct_map.c
+++ b/drivers/block/ploop/io_direct_map.c
@@ -641,6 +641,7 @@ static struct extent_map *__map_extent_bmap(struct ploop_io *io,
 {
 	struct extent_map_tree *tree = io->files.em_tree;
 	struct inode *inode = mapping->host;
+	loff_t start_off = (loff_t)start << 9;
 	struct extent_map *em;
 	struct fiemap_extent_info fieinfo;
 	struct fiemap_extent fi_extent;
@@ -681,6 +682,25 @@ again:
 	old_fs = get_fs();
 	set_fs(KERNEL_DS);
 	ret = inode->i_op->fiemap(inode, &fieinfo, start << 9, 1);
+
+	/* chase for PSBM-26762: em->block_start == 0 */
+	if (!ret && fieinfo.fi_extents_mapped == 1 &&
+	    !(fi_extent.fe_flags & FIEMAP_EXTENT_UNWRITTEN) &&
+	    (fi_extent.fe_physical >> 9) == 0) {
+		/* see how ext4_fill_fiemap_extents() implemented */
+		if (!(fi_extent.fe_flags & FIEMAP_EXTENT_DELALLOC)) {
+			printk("bad fiemap(%ld,%ld) on inode=%p &fieinfo=%p"
+			" i_size=%lld\n", start, len, inode, &fieinfo,
+			i_size_read(inode));
+			BUG();
+		}
+		/* complain about delalloc case -- ploop always fallocate
+		* before buffered write */
+		WARN(1, "ploop%d: delalloc extent [%lld,%lld] for [%lld,%ld];"
+			" i_size=%lld\n", io->plo->index, fi_extent.fe_logical,
+			fi_extent.fe_length, start_off, len << 9, i_size_read(inode));
+		ret = -ENOENT;
+	}
 	set_fs(old_fs);
 
 	if (ret) {
@@ -808,9 +828,10 @@ void trim_extent_mappings(struct extent_map_tree *tree, sector_t start)
 
 	while ((em = lookup_extent_mapping(tree, start, ((sector_t)(-1ULL)) - start))) {
 		remove_extent_mapping(tree, em);
+		WARN_ON(atomic_read(&em->refs) != 2);
 		/* once for us */
 		extent_put(em);
-		/* _XXX_ This cannot be correct in the case of concurrent lookups */
+		/* No concurrent lookups due to ploop_quiesce(). See WARN_ON above */
 		/* once for the tree */
 		extent_put(em);
 	}
-- 
1.9.3




More information about the Devel mailing list