[Devel] [PATCH RHEL9 COMMIT] dm-ploop: Fix file handle leaks when merging deltas
Konstantin Khorenko
khorenko at virtuozzo.com
Sun Oct 5 20:11:51 MSK 2025
The commit is pushed to "branch-rh9-5.14.0-427.77.1.vz9.86.x-ovz" and will appear at git at bitbucket.org:openvz/vzkernel.git
after rh9-5.14.0-427.77.1.vz9.86.11
------>
commit 1418a2731353ca69e1f70c477bbb32fb39506ae0
Author: Vasileios Almpanis <vasileios.almpanis at virtuozzo.com>
Date: Wed Oct 1 12:21:16 2025 +0000
dm-ploop: Fix file handle leaks when merging deltas
When merging deltas, we rewrite the deltas array and remove the lower
delta. Each delta holds file handles for its runners, but these were not
being released. On vStorage, the files were deleted but a
temporary handle remained, causing EBUSY errors until reboot. As a
result, directories containing snapshots could not be deleted.
https://virtuozzo.atlassian.net/browse/VSTOR-116285
Signed-off-by: Vasileios Almpanis <vasileios.almpanis at virtuozzo.com>
Reviewed-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
Feature: dm-ploop: ploop target driver
---
drivers/md/dm-ploop-bat.c | 18 ++++++++++++++++++
drivers/md/dm-ploop-cmd.c | 11 +++++------
drivers/md/dm-ploop-target.c | 15 ++-------------
drivers/md/dm-ploop.h | 1 +
4 files changed, 26 insertions(+), 19 deletions(-)
diff --git a/drivers/md/dm-ploop-bat.c b/drivers/md/dm-ploop-bat.c
index 88b1d02b47d55..a0b678b30b973 100644
--- a/drivers/md/dm-ploop-bat.c
+++ b/drivers/md/dm-ploop-bat.c
@@ -526,3 +526,21 @@ int ploop_add_delta(struct ploop *ploop, u32 level, struct file *file, bool is_r
return ret;
}
ALLOW_ERROR_INJECTION(ploop_add_delta, ERRNO);
+
+void ploop_put_delta(struct ploop *ploop, struct ploop_delta *delta)
+{
+ int i;
+
+ if (delta->file) {
+ vfs_fsync(delta->file, 1);
+ fput(delta->file);
+ }
+
+ if (delta->mtfile) {
+ for (i = 0; i < ploop->nkt_runners; i++) {
+ if (delta->mtfile[i])
+ fput(delta->mtfile[i]);
+ }
+ kfree(delta->mtfile);
+ }
+}
diff --git a/drivers/md/dm-ploop-cmd.c b/drivers/md/dm-ploop-cmd.c
index 2043162164be1..5fa78e6cff9a4 100644
--- a/drivers/md/dm-ploop-cmd.c
+++ b/drivers/md/dm-ploop-cmd.c
@@ -723,7 +723,6 @@ ALLOW_ERROR_INJECTION(ploop_process_merge_latest_snapshot, ERRNO);
static int ploop_merge_latest_snapshot(struct ploop *ploop)
{
- struct file *file;
u8 level;
int ret;
@@ -744,10 +743,11 @@ static int ploop_merge_latest_snapshot(struct ploop *ploop)
goto out;
level = ploop->nr_deltas - 2;
- file = ploop->deltas[level].file;
+
+ ploop_put_delta(ploop, &ploop->deltas[level]);
+
ploop->deltas[level] = ploop->deltas[level + 1];
ploop->nr_deltas--;
- fput(file);
ploop_resume_submitting_pios(ploop);
out:
@@ -762,7 +762,6 @@ static void notify_delta_merged(struct ploop *ploop, u8 level,
u32 i, end, *bat_entries, *d_bat_entries;
struct md_page *md, *d_md;
struct rb_node *node;
- struct file *file;
bool stop = false;
unsigned long flags;
u32 clu;
@@ -817,13 +816,13 @@ static void notify_delta_merged(struct ploop *ploop, u8 level,
d_md = ploop_md_next_entry(d_md);
}
- file = ploop->deltas[level].file;
+ ploop_put_delta(ploop, &ploop->deltas[level]);
+
/* Renumber deltas above @level */
for (i = level + 1; i < ploop->nr_deltas; i++)
ploop->deltas[i - 1] = ploop->deltas[i];
memset(&ploop->deltas[--ploop->nr_deltas], 0,
sizeof(struct ploop_delta));
- fput(file);
}
static int ploop_process_update_delta_index(struct ploop *ploop, u8 level,
diff --git a/drivers/md/dm-ploop-target.c b/drivers/md/dm-ploop-target.c
index 89a2b520ca32e..ec12c5d2a2c36 100644
--- a/drivers/md/dm-ploop-target.c
+++ b/drivers/md/dm-ploop-target.c
@@ -202,20 +202,9 @@ static void ploop_destroy(struct ploop *ploop)
for (i = 0; i < 2; i++)
percpu_ref_exit(&ploop->inflight_bios_ref[i]);
/* Nobody uses it after destroy_workqueue() */
- while (ploop->nr_deltas-- > 0) {
- if (ploop->deltas[ploop->nr_deltas].file) {
- vfs_fsync(ploop->deltas[ploop->nr_deltas].file, 1);
- fput(ploop->deltas[ploop->nr_deltas].file);
- }
+ while (ploop->nr_deltas-- > 0)
+ ploop_put_delta(ploop, &ploop->deltas[ploop->nr_deltas]);
- if (ploop->deltas[ploop->nr_deltas].mtfile) {
- for (i = 0; i < ploop->nkt_runners; i++) {
- if (ploop->deltas[ploop->nr_deltas].mtfile[i])
- fput(ploop->deltas[ploop->nr_deltas].mtfile[i]);
- }
- }
- kfree(ploop->deltas[ploop->nr_deltas].mtfile);
- }
WARN_ON(ploop_has_pending_activity(ploop));
WARN_ON(!ploop_empty_htable(ploop->exclusive_pios));
WARN_ON(!ploop_empty_htable(ploop->inflight_pios));
diff --git a/drivers/md/dm-ploop.h b/drivers/md/dm-ploop.h
index 54d51ab8126ba..fc12efeb0cd93 100644
--- a/drivers/md/dm-ploop.h
+++ b/drivers/md/dm-ploop.h
@@ -600,6 +600,7 @@ extern bool ploop_try_update_bat_entry(struct ploop *ploop, u32 clu,
extern int ploop_add_delta(struct ploop *ploop, u32 level,
struct file *file, bool is_raw);
+extern void ploop_put_delta(struct ploop *ploop, struct ploop_delta *delta);
extern int ploop_check_delta_length(struct ploop *ploop, struct file *file,
loff_t *file_size);
extern void ploop_submit_embedded_pios(struct ploop *ploop,
More information about the Devel
mailing list