[Devel] [PATCH v5 vz9/vz10] dm-ploop: Fix file handle leaks when merging deltas

Pavel Tikhomirov ptikhomirov at virtuozzo.com
Thu Oct 2 05:46:46 MSK 2025



On 10/1/25 20:21, Vasileios Almpanis wrote:
> 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

Reviewed-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>

> 
> Signed-off-by: Vasileios Almpanis <vasileios.almpanis at virtuozzo.com>
> Feature: dm-ploop: ploop target driver
> ---
> 
> v2: Extract delta cleanup into helper function.
> v3: Removes unused variable.
> v4: Fixes styling issues.
> v5: Removes unused variable.
> ---
>   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 88b1d02b47d5..a0b678b30b97 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 2043162164be..5fa78e6cff9a 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 89a2b520ca32..ec12c5d2a2c3 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 54d51ab8126b..fc12efeb0cd9 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,

-- 
Best regards, Pavel Tikhomirov
Senior Software Developer, Virtuozzo.



More information about the Devel mailing list