The lqe_glbl_data in "struct lquota_entry" is allocated in
qmt_lvbo_init and freed in qmt_lvbo_free, it could be freed
during qmt_seed_glbe called by qmt_set_id_notify, and cause
panic because of using freed memory.
Signed-off-by: Hongchao Zhang <hongchao@whamcloud.com>
Change-Id: I274f07ee8609c83852572be51625cc929a9130ec
Reviewed-on: https://review.whamcloud.com/45098
Reviewed-by: Sergey Cheremencev <sergey.cheremencev@hpe.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lqe_is_global:1, /* lqe belongs to global pool "0x0"*/
lqe_is_deleted:1; /* lqe will be deleted soon */
lqe_is_global:1, /* lqe belongs to global pool "0x0"*/
lqe_is_deleted:1; /* lqe will be deleted soon */
+ /* the lock to protect lqe_glbl_data */
+ struct mutex lqe_glbl_data_lock;
struct lqe_glbl_data *lqe_glbl_data;
};
struct lqe_glbl_data *lqe_glbl_data;
};
lqe->lqe_revoke_time = 0;
init_rwsem(&lqe->lqe_sem);
lqe->lqe_revoke_time = 0;
init_rwsem(&lqe->lqe_sem);
+ mutex_init(&lqe->lqe_glbl_data_lock);
}
/* Apply the default quota setting to the specified quota entry
}
/* Apply the default quota setting to the specified quota entry
- if (lqe_gl->lqe_glbl_data && need_reseed) {
- qmt_seed_glbe_all(env, lqe_gl->lqe_glbl_data, qunit, edquot);
+ if (need_reseed) {
+ mutex_lock(&lqe_gl->lqe_glbl_data_lock);
+ if (lqe_gl->lqe_glbl_data)
+ qmt_seed_glbe_all(env, lqe_gl->lqe_glbl_data, qunit,
+ edquot);
+ mutex_unlock(&lqe_gl->lqe_glbl_data_lock);
+
qmt_id_lock_notify(qmt, lqe_gl);
}
return need_reseed;
qmt_id_lock_notify(qmt, lqe_gl);
}
return need_reseed;
for (i = 0; i < qti_lqes_cnt(env); i++)
need_notify |= qmt_revalidate(env, qti_lqes(env)[i]);
for (i = 0; i < qti_lqes_cnt(env); i++)
need_notify |= qmt_revalidate(env, qti_lqes(env)[i]);
+ if (!need_notify)
+ return;
+
/* There could be no ID lock to the moment of reconciliation.
* As a result lqe global data is not initialised yet. It is ok
* for release and report requests. */
if (!lqe_gl->lqe_glbl_data &&
/* There could be no ID lock to the moment of reconciliation.
* As a result lqe global data is not initialised yet. It is ok
* for release and report requests. */
if (!lqe_gl->lqe_glbl_data &&
- (req_is_rel(qb_flags) || req_has_rep(qb_flags)))
+ (req_is_rel(qb_flags) || req_has_rep(qb_flags))) {
+ mutex_lock(&lqe_gl->lqe_glbl_data_lock);
+ if (lqe_gl->lqe_glbl_data)
qmt_seed_glbe(env, lqe_gl->lqe_glbl_data);
qmt_seed_glbe(env, lqe_gl->lqe_glbl_data);
- qmt_id_lock_notify(qmt, lqe_gl);
- }
+ mutex_unlock(&lqe_gl->lqe_glbl_data_lock);
+
+ qmt_id_lock_notify(qmt, lqe_gl);
}
void qti_lqes_init(const struct lu_env *env)
}
void qti_lqes_init(const struct lu_env *env)
if (!lqe_gl)
GOTO(lqes_fini, rc);
if (!lqe_gl)
GOTO(lqes_fini, rc);
+ mutex_lock(&lqe_gl->lqe_glbl_data_lock);
if (lqe_gl->lqe_glbl_data)
qmt_seed_glbe(env, lqe_gl->lqe_glbl_data);
if (lqe_gl->lqe_glbl_data)
qmt_seed_glbe(env, lqe_gl->lqe_glbl_data);
+ mutex_unlock(&lqe_gl->lqe_glbl_data_lock);
+
/* Even if slaves haven't enqueued quota lock yet,
* it is needed to set lqe_revoke_time in qmt_id_lock_glimpse
* in case of reaching qpi_least_qunit */
/* Even if slaves haven't enqueued quota lock yet,
* it is needed to set lqe_revoke_time in qmt_id_lock_glimpse
* in case of reaching qpi_least_qunit */
struct lquota_entry *lqe = res->lr_lvb_data;
struct lqe_glbl_data *lgd = lqe->lqe_glbl_data;
struct lquota_entry *lqe = res->lr_lvb_data;
struct lqe_glbl_data *lgd = lqe->lqe_glbl_data;
- /* release lqe reference */
+ mutex_lock(&lqe->lqe_glbl_data_lock);
lqe->lqe_glbl_data = NULL;
lqe->lqe_glbl_data = NULL;
+ mutex_unlock(&lqe->lqe_glbl_data_lock);
+
+ /* release lqe reference */
+ lqe_putref(lqe);
} else {
struct dt_object *obj = res->lr_lvb_data;
/* release object reference */
} else {
struct dt_object *obj = res->lr_lvb_data;
/* release object reference */
init_waitqueue_head(&lqe->lqe_waiters);
lqe->lqe_usage = 0;
lqe->lqe_nopreacq = false;
init_waitqueue_head(&lqe->lqe_waiters);
lqe->lqe_usage = 0;
lqe->lqe_nopreacq = false;
+ mutex_init(&lqe->lqe_glbl_data_lock);