@@ -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;
@@ -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,
@@ -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);
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(+)