ploop: Repopulate holes_bitmap on changing delta

Submitted by Kirill Tkhai on April 17, 2019, 11:17 a.m.

Details

Message ID 155549982225.22192.15815669734828656421.stgit@localhost.localdomain
State New
Series "ploop: Repopulate holes_bitmap on changing delta"
Headers show

Commit Message

Kirill Tkhai April 17, 2019, 11:17 a.m.
New delta is black box, and holes may be anywhere.
So, we have to populate holes_bitmap in this case.

Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 drivers/block/ploop/dev.c        |    9 +++++++++
 drivers/block/ploop/fmt_ploop1.c |   20 ++++++++++++++++++++
 include/linux/ploop/ploop.h      |    1 +
 3 files changed, 30 insertions(+)

Patch hide | download patch | download mbox

diff --git a/drivers/block/ploop/dev.c b/drivers/block/ploop/dev.c
index 37685356d08a..8d93a2a861bd 100644
--- a/drivers/block/ploop/dev.c
+++ b/drivers/block/ploop/dev.c
@@ -3389,6 +3389,12 @@  static int ploop_replace_delta(struct ploop_device * plo, unsigned long arg)
 		goto out_close;
 	}
 
+	if (delta->ops->replace_delta) {
+		err = delta->ops->replace_delta(delta);
+		if (err)
+			goto out_kobj_del;
+	}
+
 	ploop_quiesce(plo);
 	ploop_map_destroy(&plo->map);
 	list_replace_init(&old_delta->list, &delta->list);
@@ -3404,6 +3410,9 @@  static int ploop_replace_delta(struct ploop_device * plo, unsigned long arg)
 	kobject_put(&old_delta->kobj);
 	return 0;
 
+out_kobj_del:
+	kobject_del(&delta->kobj);
+	kobject_put(&plo->kobj);
 out_close:
 	delta->ops->stop(delta);
 out_destroy:
diff --git a/drivers/block/ploop/fmt_ploop1.c b/drivers/block/ploop/fmt_ploop1.c
index 32c9a08e0e84..32437175dadb 100644
--- a/drivers/block/ploop/fmt_ploop1.c
+++ b/drivers/block/ploop/fmt_ploop1.c
@@ -582,6 +582,25 @@  ploop1_complete_merge(struct ploop_delta *delta)
 	return populate_holes_bitmap(delta, ph);
 }
 
+static int
+ploop1_replace_delta(struct ploop_delta *delta)
+{
+	struct ploop1_private *ph = delta->priv;
+	struct ploop_device *plo = delta->plo;
+
+	if (delta->level != 0)
+		return 0;
+
+	/*
+	 * @delta is not linked, but old delta is still in list.
+	 * So, we check whether old delta is only element there.
+	 */
+	if (!list_is_singular(&plo->map.delta_list))
+		return 0;
+
+	return populate_holes_bitmap(delta, ph);
+}
+
 static int ploop1_truncate(struct ploop_delta * delta, struct file * file,
 			   __u32 alloc_head)
 {
@@ -819,6 +838,7 @@  static struct ploop_delta_ops ploop1_delta_ops =
 	.fmt_prepare_merge =	ploop1_prepare_merge,
 	.start_merge	=	ploop1_start_merge,
 	.complete_merge =	ploop1_complete_merge,
+	.replace_delta 	=	ploop1_replace_delta,
 	.truncate	=	ploop1_truncate,
 	.prepare_grow	=	ploop1_prepare_grow,
 	.complete_grow	=	ploop1_complete_grow,
diff --git a/include/linux/ploop/ploop.h b/include/linux/ploop/ploop.h
index 7a77e674fe74..230c51ecba87 100644
--- a/include/linux/ploop/ploop.h
+++ b/include/linux/ploop/ploop.h
@@ -284,6 +284,7 @@  struct ploop_delta_ops
 	int		(*fmt_prepare_merge)(struct ploop_delta *, struct ploop_snapdata *);
 	int		(*start_merge)(struct ploop_delta *, struct ploop_snapdata *);
 	int		(*complete_merge)(struct ploop_delta *);
+	int		(*replace_delta)(struct ploop_delta *);
 	int		(*truncate)(struct ploop_delta *, struct file *, __u32 alloc_head);
 	int		(*prepare_grow)(struct ploop_delta *, u64 *new_size, int *reloc);
 	int		(*complete_grow)(struct ploop_delta *, u64 new_size);