[Devel] [PATCH RH7 1/2] ploop: Preallocate clusters before nullifying on grow

Kirill Tkhai ktkhai at virtuozzo.com
Mon Oct 26 15:46:25 MSK 2020


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 at 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(+)

diff --git a/drivers/block/ploop/fmt_ploop1.c b/drivers/block/ploop/fmt_ploop1.c
index 99acad2d6994..316f62621c33 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 f67ce47e0562..dff12e2276bb 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 16a30076704a..bffd83b08764 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);
 




More information about the Devel mailing list