parallelize: Fix race condition

In situation when all the shards finish their work before parallelize
loop does it's final loop condition check, which involves access to
parallelize object, it's possible that parallelize object will be
deinitialized before this final access.

Increasing refcount by 1 before running parallelize and decreasing it
only after the loop is finished addresses this problem.

Signed-off-by: Robert Baldyga <robert.baldyga@huawei.com>
Signed-off-by: Michal Mielewczyk <michal.mielewczyk@huawei.com>
This commit is contained in:
Robert Baldyga 2023-07-26 04:04:09 +02:00 committed by Michal Mielewczyk
parent 55b99518ed
commit 5e6a90a293

View File

@ -25,11 +25,25 @@ struct ocf_parallelize {
struct ocf_request *reqs[]; struct ocf_request *reqs[];
}; };
static void _ocf_parallelize_finish(ocf_parallelize_t parallelize)
{
ocf_parallelize_finish_t finish;
void *priv;
int error;
if (env_atomic_dec_return(&parallelize->remaining))
return;
finish = parallelize->finish;
priv = parallelize->priv;
error = env_atomic_read(&parallelize->error);
finish(parallelize, priv, error);
}
static int _ocf_parallelize_hndl(struct ocf_request *req) static int _ocf_parallelize_hndl(struct ocf_request *req)
{ {
ocf_parallelize_t parallelize = req->priv; ocf_parallelize_t parallelize = req->priv;
ocf_parallelize_finish_t finish;
void *priv;
int error; int error;
error = parallelize->handle(parallelize, parallelize->priv, error = parallelize->handle(parallelize, parallelize->priv,
@ -37,14 +51,7 @@ static int _ocf_parallelize_hndl(struct ocf_request *req)
env_atomic_cmpxchg(&parallelize->error, 0, error); env_atomic_cmpxchg(&parallelize->error, 0, error);
if (env_atomic_dec_return(&parallelize->remaining)) _ocf_parallelize_finish(parallelize);
return 0;
finish = parallelize->finish;
priv = parallelize->priv;
error = env_atomic_read(&parallelize->error);
finish(parallelize, priv, error);
return 0; return 0;
} }
@ -84,7 +91,7 @@ int ocf_parallelize_create(ocf_parallelize_t *parallelize,
tmp_parallelize->finish = finish; tmp_parallelize->finish = finish;
tmp_parallelize->shards_cnt = shards_cnt; tmp_parallelize->shards_cnt = shards_cnt;
env_atomic_set(&tmp_parallelize->remaining, shards_cnt); env_atomic_set(&tmp_parallelize->remaining, shards_cnt + 1);
env_atomic_set(&tmp_parallelize->error, 0); env_atomic_set(&tmp_parallelize->error, 0);
@ -149,4 +156,6 @@ void ocf_parallelize_run(ocf_parallelize_t parallelize)
for (i = 0; i < parallelize->shards_cnt; i++) for (i = 0; i < parallelize->shards_cnt; i++)
ocf_queue_push_req(parallelize->reqs[i], OCF_QUEUE_PRIO_HIGH); ocf_queue_push_req(parallelize->reqs[i], OCF_QUEUE_PRIO_HIGH);
_ocf_parallelize_finish(parallelize);
} }