[Devel] [PATCH RHEL7 COMMIT] ploop: bug on bad fiemap (v2)

Konstantin Khorenko khorenko at odin.com
Mon May 18 21:27:05 PDT 2015


The commit is pushed to "branch-rh7-3.10.0-123.1.2-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-123.1.2.vz7.5.1
------>
commit e3b634ed036e618d74643faaa478dc3951c2f781
Author: Andrey Smetanin <asmetanin at virtuozzo.com>
Date:   Tue May 19 08:27:05 2015 +0400

    ploop: bug on bad fiemap (v2)
    
    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);
 	}



More information about the Devel mailing list