Skip to content

Commit

Permalink
libmultipath: io_err_stat: don't free aio memory before completion
Browse files Browse the repository at this point in the history
It is wrong to assume that aio data structures can be reused or freed
after io_cancel(). io_cancel() will almost always return -EINPROGRESS,
anyway. Use the io_starttime field to indicate whether an io event
has been completed by the kernel. Make sure no in-flight buffers are freed.

Fixes opensvc#73.

Signed-off-by: Martin Wilck <[email protected]>
Cc: Li Xiao Keng <[email protected]>
Cc: Miao Guanqin <[email protected]>
  • Loading branch information
mwilck committed Oct 24, 2023
1 parent 15eddaa commit 3e07043
Showing 1 changed file with 16 additions and 10 deletions.
26 changes: 16 additions & 10 deletions libmultipath/io_err_stat.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,14 @@ static int init_each_dio_ctx(struct dio_ctx *ct, int blksize,
return 0;
}

static void deinit_each_dio_ctx(struct dio_ctx *ct)
static int deinit_each_dio_ctx(struct dio_ctx *ct)
{
if (ct->buf)
free(ct->buf);
if (!ct->buf)
return 0;
if (ct->io_starttime.tv_sec != 0 || ct->io_starttime.tv_nsec != 0)
return 1;
free(ct->buf);
return 0;
}

static int setup_directio_ctx(struct io_err_stat_path *p)
Expand Down Expand Up @@ -164,6 +168,7 @@ static int setup_directio_ctx(struct io_err_stat_path *p)
static void free_io_err_stat_path(struct io_err_stat_path *p)
{
int i;
int inflight = 0;

if (!p)
return;
Expand All @@ -173,8 +178,13 @@ static void free_io_err_stat_path(struct io_err_stat_path *p)
cancel_inflight_io(p);

for (i = 0; i < CONCUR_NR_EVENT; i++)
deinit_each_dio_ctx(p->dio_ctx_array + i);
free(p->dio_ctx_array);
inflight += deinit_each_dio_ctx(p->dio_ctx_array + i);

if (!inflight)
free(p->dio_ctx_array);
else
io_err_stat_log(2, "%s: can't free aio space of %s, %d IOs in flight",
__func__, p->devname, inflight);

if (p->fd > 0)
close(p->fd);
Expand Down Expand Up @@ -503,7 +513,7 @@ static int try_to_cancel_timeout_io(struct dio_ctx *ct, struct timespec *t,
int rc = PATH_UNCHECKED;
int r;

if (ct->io_starttime.tv_sec == 0)
if (ct->io_starttime.tv_sec == 0 && ct->io_starttime.tv_nsec == 0)
return rc;
timespecsub(t, &ct->io_starttime, &difftime);
if (difftime.tv_sec > IOTIMEOUT_SEC) {
Expand All @@ -514,8 +524,6 @@ static int try_to_cancel_timeout_io(struct dio_ctx *ct, struct timespec *t,
if (r)
io_err_stat_log(5, "%s: io_cancel error %i",
dev, errno);
ct->io_starttime.tv_sec = 0;
ct->io_starttime.tv_nsec = 0;
rc = PATH_TIMEOUT;
} else {
rc = PATH_PENDING;
Expand Down Expand Up @@ -559,8 +567,6 @@ static void cancel_inflight_io(struct io_err_stat_path *pp)
if (r)
io_err_stat_log(5, "%s: io_cancel error %d, %i",
pp->devname, r, errno);
ct->io_starttime.tv_sec = 0;
ct->io_starttime.tv_nsec = 0;
}
}

Expand Down

0 comments on commit 3e07043

Please sign in to comment.