[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