diff mbox series

[v2,05/14] libmultipath: io_err_stat: call io_destroy() inside free_io_err_pathvec()

Message ID 20231026174153.1133-6-mwilck@suse.com (mailing list archive)
State Not Applicable, archived
Delegated to: christophe varoqui
Headers show
Series multipath: aio, systemd, and documentation improvements | expand

Commit Message

Martin Wilck Oct. 26, 2023, 5:41 p.m. UTC
From: Martin Wilck <mwilck@suse.com>

Memory used by aio iocbs must not be freed before either all iocbs
have finished, or io_destroy() has been called (which will wait until
all iocbs have finished).

Don't call cancel_inflight_io() from free_io_err_stat_path(). Rather,
cancel directly from free_io_err_pathvec(). This way we make sure that
we can't call io_cancel() with an already destroyed ioctx, and that
we don't free memory of in-flight requests.

The other callers of free_io_err_stat_path() also don't need to call
cancel_inflight_io(). In service_paths(), where free_io_err_stat_path()
it is called for paths on which all IO has either finished or timed out,
hanging requests will already have been cancelled in the
try_to_cancel_timeout_io() code path (note that total_time is at least
2 * IO_TIMEOUT_SEC). In the failure case of enqueue_io_err_stat_by_path(), no
IO has been submitted yet.

Signed-off-by: Martin Wilck <mwilck@suse.com>
Cc: Li Xiao Keng <lixiaokeng@huawei.com>
Cc: Miao Guanqin <miaoguanqin@huawei.com>
Cc: Guan Junxiong <guanjunxiong@huawei.com>
---
 libmultipath/io_err_stat.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

Comments

Benjamin Marzinski Oct. 27, 2023, 6:55 p.m. UTC | #1
On Thu, Oct 26, 2023 at 07:41:44PM +0200, mwilck@suse.com wrote:
> From: Martin Wilck <mwilck@suse.com>
> 
> Memory used by aio iocbs must not be freed before either all iocbs
> have finished, or io_destroy() has been called (which will wait until
> all iocbs have finished).
> 
> Don't call cancel_inflight_io() from free_io_err_stat_path(). Rather,
> cancel directly from free_io_err_pathvec(). This way we make sure that
> we can't call io_cancel() with an already destroyed ioctx, and that
> we don't free memory of in-flight requests.
> 
> The other callers of free_io_err_stat_path() also don't need to call
> cancel_inflight_io(). In service_paths(), where free_io_err_stat_path()
> it is called for paths on which all IO has either finished or timed out,
> hanging requests will already have been cancelled in the
> try_to_cancel_timeout_io() code path (note that total_time is at least
> 2 * IO_TIMEOUT_SEC). In the failure case of enqueue_io_err_stat_by_path(), no
> IO has been submitted yet.
> 
> Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
> Cc: Li Xiao Keng <lixiaokeng@huawei.com>
> Cc: Miao Guanqin <miaoguanqin@huawei.com>
> Cc: Guan Junxiong <guanjunxiong@huawei.com>
> ---
>  libmultipath/io_err_stat.c | 12 +++++++++---
>  1 file changed, 9 insertions(+), 3 deletions(-)
> 
> diff --git a/libmultipath/io_err_stat.c b/libmultipath/io_err_stat.c
> index c474c34..3f32e32 100644
> --- a/libmultipath/io_err_stat.c
> +++ b/libmultipath/io_err_stat.c
> @@ -175,8 +175,6 @@ static void free_io_err_stat_path(struct io_err_stat_path *p)
>  	if (!p->dio_ctx_array)
>  		goto free_path;
>  
> -	cancel_inflight_io(p);
> -
>  	for (i = 0; i < CONCUR_NR_EVENT; i++)
>  		inflight += deinit_each_dio_ctx(p->dio_ctx_array + i);
>  
> @@ -221,6 +219,15 @@ static void free_io_err_pathvec(void)
>  	pthread_cleanup_push(cleanup_mutex, &io_err_pathvec_lock);
>  	if (!io_err_pathvec)
>  		goto out;
> +
> +	/* io_cancel() is a noop, but maybe in the future it won't be */
> +	vector_foreach_slot(io_err_pathvec, path, i) {
> +		if (path && path->dio_ctx_array)
> +			cancel_inflight_io(path);
> +	}
> +
> +	/* This blocks until all I/O is finished */
> +	io_destroy(ioctx);
>  	vector_foreach_slot(io_err_pathvec, path, i)
>  		free_io_err_stat_path(path);
>  	vector_free(io_err_pathvec);
> @@ -752,5 +759,4 @@ void stop_io_err_stat_thread(void)
>  
>  	pthread_join(io_err_stat_thr, NULL);
>  	free_io_err_pathvec();
> -	io_destroy(ioctx);
>  }
> -- 
> 2.42.0
diff mbox series

Patch

diff --git a/libmultipath/io_err_stat.c b/libmultipath/io_err_stat.c
index c474c34..3f32e32 100644
--- a/libmultipath/io_err_stat.c
+++ b/libmultipath/io_err_stat.c
@@ -175,8 +175,6 @@  static void free_io_err_stat_path(struct io_err_stat_path *p)
 	if (!p->dio_ctx_array)
 		goto free_path;
 
-	cancel_inflight_io(p);
-
 	for (i = 0; i < CONCUR_NR_EVENT; i++)
 		inflight += deinit_each_dio_ctx(p->dio_ctx_array + i);
 
@@ -221,6 +219,15 @@  static void free_io_err_pathvec(void)
 	pthread_cleanup_push(cleanup_mutex, &io_err_pathvec_lock);
 	if (!io_err_pathvec)
 		goto out;
+
+	/* io_cancel() is a noop, but maybe in the future it won't be */
+	vector_foreach_slot(io_err_pathvec, path, i) {
+		if (path && path->dio_ctx_array)
+			cancel_inflight_io(path);
+	}
+
+	/* This blocks until all I/O is finished */
+	io_destroy(ioctx);
 	vector_foreach_slot(io_err_pathvec, path, i)
 		free_io_err_stat_path(path);
 	vector_free(io_err_pathvec);
@@ -752,5 +759,4 @@  void stop_io_err_stat_thread(void)
 
 	pthread_join(io_err_stat_thr, NULL);
 	free_io_err_pathvec();
-	io_destroy(ioctx);
 }