[RHEL7,COMMIT] ploop: Preallocate clusters before nullifying on grow

Submitted by Vasily Averin on Oct. 29, 2020, 8:15 p.m.

Details

Message ID 202010292015.09TKFDQ4017086@vz7build.vvs.sw.ru
State New
Series "Series without cover letter"
Headers show

Commit Message

Vasily Averin Oct. 29, 2020, 8:15 p.m.
The commit is pushed to "branch-rh7-3.10.0-1127.18.2.vz7.163.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-1127.18.2.vz7.163.42
------>
commit 163d72f3dde897256ab957c24f02e308146dbfc9
Author: Kirill Tkhai <ktkhai@virtuozzo.com>
Date:   Thu Oct 29 23:15:13 2020 +0300

    ploop: Preallocate clusters before nullifying on grow
    
    In case of future BAT clusters are data clusters and
    there is a hole, nullifying code fails since there is
    no extent. Fix that by future BAT preallocation.
    
    https://jira.sw.ru/browse/PSBM-121772
    Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 drivers/block/ploop/fmt_ploop1.c |  8 ++++++++
 drivers/block/ploop/io_direct.c  | 26 ++++++++++++++++++++++++++
 include/linux/ploop/ploop.h      |  2 ++
 3 files changed, 36 insertions(+)

Patch hide | download patch | download mbox

diff --git a/drivers/block/ploop/fmt_ploop1.c b/drivers/block/ploop/fmt_ploop1.c
index 4fad1ba..26e7001 100644
--- a/drivers/block/ploop/fmt_ploop1.c
+++ b/drivers/block/ploop/fmt_ploop1.c
@@ -10,6 +10,7 @@ 
 #include <linux/version.h>
 #include <linux/fs.h>
 #include <linux/file.h>
+#include <uapi/linux/falloc.h>
 
 #include <linux/ploop/ploop.h>
 #include "ploop1_image.h"
@@ -775,6 +776,13 @@  ploop1_prepare_grow(struct ploop_delta * delta, u64 *new_size, int *reloc)
 		delta->io.plo->grow_start = n_present;
 		delta->io.plo->grow_end = n_needed - n_alloced - 1;
 
+		if (delta->io.ops->prepare_reloc) {
+			err = delta->io.ops->prepare_reloc(&delta->io,
+					delta->io.plo->grow_start, *reloc);
+			if (err)
+				return err;
+		}
+
 		/* Does not use rellocated data clusters during grow. */
 		if (delta->holes_bitmap) {
 			i = delta->io.plo->grow_start;
diff --git a/drivers/block/ploop/io_direct.c b/drivers/block/ploop/io_direct.c
index f67ce47..dff12e2 100644
--- a/drivers/block/ploop/io_direct.c
+++ b/drivers/block/ploop/io_direct.c
@@ -1666,6 +1666,31 @@  static int dio_start_merge(struct ploop_io * io, struct ploop_snapdata *sd)
 	return 0;
 }
 
+/*
+ * There may be a hole in a place, which will be new BAT clusters
+ * after grow (before grow these clusters are data). Nullifying code
+ * expects there is no a hole, so we preallocate them here.
+ */
+static int dio_prepare_reloc(struct ploop_io *io, unsigned int start_clu,
+			     unsigned int nr)
+{
+	struct file *file = io->files.file;
+	int log = io->plo->cluster_log;
+	loff_t start, len;
+	int err;
+
+	start = start_clu << (log + 9);
+	len = nr << (log + 9);
+
+	err = file->f_op->fallocate(file, 0, start, len);
+	if (err)
+		return err;
+	err = file->f_op->fallocate(file, FALLOC_FL_CONVERT_UNWRITTEN,
+				    start, len);
+	return err;
+
+}
+
 static void dio_unplug(struct ploop_io * io)
 {	
 	/* Need more thinking how to implement unplug */
@@ -1802,6 +1827,7 @@  static struct ploop_io_ops ploop_io_ops_direct =
 	.complete_snapshot =	dio_complete_snapshot,
 	.io_prepare_merge =	dio_prepare_merge,
 	.start_merge	=	dio_start_merge,
+	.prepare_reloc	=	dio_prepare_reloc,
 	.truncate	=	dio_truncate,
 
 	.queue_settings	=	dio_queue_settings,
diff --git a/include/linux/ploop/ploop.h b/include/linux/ploop/ploop.h
index 16a3007..bffd83b 100644
--- a/include/linux/ploop/ploop.h
+++ b/include/linux/ploop/ploop.h
@@ -198,6 +198,8 @@  struct ploop_io_ops
 	int	(*complete_snapshot)(struct ploop_io *, struct ploop_snapdata *);
 	int	(*io_prepare_merge)(struct ploop_io *, struct ploop_snapdata *);
 	int	(*start_merge)(struct ploop_io *, struct ploop_snapdata *);
+	int	(*prepare_reloc)(struct ploop_io *, unsigned int, unsigned int);
+
 	int	(*truncate)(struct ploop_io *, struct file *, __u32 alloc_head);
 	void	(*queue_settings)(struct ploop_io *, struct request_queue *q);