[RHEL7,COMMIT] ploop: Repopulate holes_bitmap on changing delta

Submitted by Konstantin Khorenko on April 19, 2019, 3:34 p.m.

Details

Message ID 201904191534.x3JFYBtM007398@finist-ce7.sw.ru
State New
Series "ploop: Repopulate holes_bitmap on changing delta"
Headers show

Commit Message

Konstantin Khorenko April 19, 2019, 3:34 p.m.
The commit is pushed to "branch-rh7-3.10.0-957.10.1.vz7.94.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-957.10.1.vz7.94.16
------>
commit 7c9779b74d98691294a832b7bf347e89142f9940
Author: Kirill Tkhai <ktkhai@virtuozzo.com>
Date:   Wed Apr 17 14:17:12 2019 +0300

    ploop: Repopulate holes_bitmap on changing delta
    
    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        | 10 ++++++++++
 drivers/block/ploop/fmt_ploop1.c | 20 ++++++++++++++++++++
 include/linux/ploop/ploop.h      |  1 +
 3 files changed, 31 insertions(+)

Patch hide | download patch | download mbox

diff --git a/drivers/block/ploop/dev.c b/drivers/block/ploop/dev.c
index 37685356d08a..09ef4e53f806 100644
--- a/drivers/block/ploop/dev.c
+++ b/drivers/block/ploop/dev.c
@@ -3382,6 +3382,7 @@  static int ploop_replace_delta(struct ploop_device * plo, unsigned long arg)
 
 	err = KOBJECT_ADD(&delta->kobj, kobject_get(&plo->kobj),
 			  "%d", delta->level);
+	/* _put below is a pair for _get for OLD delta */
 	kobject_put(&plo->kobj);
 
 	if (err < 0) {
@@ -3389,6 +3390,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 +3411,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);