X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fquota%2Fqmt_pool.c;h=c4398a5bbd70735a2fb7fa827dafc254462784c0;hb=862f0baa7c21cb631b98d3886ef9e938f4519573;hp=37bb4888ce719dcf9e4d20e8cfdfbac222273647;hpb=d16b3141119a3b75276914ad3601e0dd27579b2b;p=fs%2Flustre-release.git diff --git a/lustre/quota/qmt_pool.c b/lustre/quota/qmt_pool.c index 37bb488..c4398a5 100644 --- a/lustre/quota/qmt_pool.c +++ b/lustre/quota/qmt_pool.c @@ -79,6 +79,8 @@ static int qpi_state_seq_show(struct seq_file *m, void *data) int type; LASSERT(pool != NULL); + if (unlikely(!test_bit(QPI_FLAG_STATE_INITED, &pool->qpi_flags))) + return -ENOENT; seq_printf(m, "pool:\n" " id: %u\n" @@ -106,6 +108,8 @@ static int qpi_soft_least_qunit_seq_show(struct seq_file *m, void *data) { struct qmt_pool_info *pool = m->private; LASSERT(pool != NULL); + if (unlikely(!test_bit(QPI_FLAG_STATE_INITED, &pool->qpi_flags))) + return -ENOENT; seq_printf(m, "%lu\n", pool->qpi_soft_least_qunit); return 0; @@ -121,6 +125,8 @@ qpi_soft_least_qunit_seq_write(struct file *file, const char __user *buffer, int rc; LASSERT(pool != NULL); + if (unlikely(!test_bit(QPI_FLAG_STATE_INITED, &pool->qpi_flags))) + return -ENOENT; /* Not tuneable for inode limit */ if (pool->qpi_rtype != LQUOTA_RES_DT) @@ -177,6 +183,7 @@ static int qmt_pool_alloc(const struct lu_env *env, struct qmt_device *qmt, init_rwsem(&pool->qpi_recalc_sem); pool->qpi_rtype = pool_type; + pool->qpi_flags = 0; /* initialize refcount to 1, hash table will then grab an additional * reference */ @@ -459,6 +466,8 @@ void qmt_pool_fini(const struct lu_env *env, struct qmt_device *qmt) /* parse list of pool and destroy each element */ list_for_each_entry_safe(pool, tmp, &qmt->qmt_pool_list, qpi_linkage) { + /* stop all recalc threads - it may hold qpi reference */ + qmt_stop_pool_recalc(pool); /* release extra reference taken in qmt_pool_alloc */ qpi_putref(env, pool); } @@ -670,6 +679,7 @@ int qmt_pool_prepare(const struct lu_env *env, struct qmt_device *qmt, qmt->qmt_svname, PFID(&qti->qti_fid), rc); #endif } + set_bit(QPI_FLAG_STATE_INITED, &pool->qpi_flags); if (name) break; } @@ -1155,6 +1165,13 @@ static int qmt_pool_recalc(void *args) pool = args; + rc = lu_env_init(&env, LCT_MD_THREAD); + if (rc) { + CERROR("%s: cannot init env: rc = %d\n", + pool->qpi_qmt->qmt_svname, rc); + GOTO(out, rc); + } + obd = qmt_get_mgc(pool->qpi_qmt); if (IS_ERR(obd)) GOTO(out, rc = PTR_ERR(obd)); @@ -1164,6 +1181,7 @@ static int qmt_pool_recalc(void *args) while (obd->obd_process_conf) schedule_timeout_uninterruptible(cfs_time_seconds(1)); + OBD_FAIL_TIMEOUT(OBD_FAIL_QUOTA_RECALC, cfs_fail_val); sem = qmt_sarr_rwsem(pool); LASSERT(sem); down_read(sem); @@ -1183,15 +1201,9 @@ static int qmt_pool_recalc(void *args) * solution looks more complex, so leave it as it is. */ down_write(&pool->qpi_recalc_sem); - rc = lu_env_init(&env, LCT_MD_THREAD); - if (rc) { - CERROR("%s: cannot init env: rc = %d\n", obd->obd_name, rc); - GOTO(out, rc); - } - glbl_pool = qmt_pool_lookup_glb(&env, pool->qpi_qmt, pool->qpi_rtype); if (IS_ERR(glbl_pool)) - GOTO(out_env, rc = PTR_ERR(glbl_pool)); + GOTO(out, rc = PTR_ERR(glbl_pool)); slaves_cnt = qmt_sarr_count(pool); CDEBUG(D_QUOTA, "Starting pool recalculation for %d slaves in %s\n", @@ -1237,8 +1249,6 @@ static int qmt_pool_recalc(void *args) GOTO(out_stop, rc); out_stop: qpi_putref(&env, glbl_pool); -out_env: - lu_env_fini(&env); out: if (xchg(&pool->qpi_recalc_task, NULL) == NULL) /* @@ -1251,12 +1261,20 @@ out: clear_bit(QPI_FLAG_RECALC_OFFSET, &pool->qpi_flags); /* Pool can't be changed, since sem has been down. - * Thus until up_read, no one can restart recalc thread. */ + * Thus until up_read, no one can restart recalc thread. + */ if (sem) { up_read(sem); up_write(&pool->qpi_recalc_sem); } - qpi_putref(&env, pool); + + /* qpi_getref has been called in qmt_start_pool_recalc, + * however we can't call qpi_putref if lu_env_init failed. + */ + if (env.le_ctx.lc_state == LCS_ENTERED) { + qpi_putref(&env, pool); + lu_env_fini(&env); + } return rc; } @@ -1349,6 +1367,9 @@ static int qmt_pool_add_rem(struct obd_device *obd, char *poolname, int rc, idx; ENTRY; + if (qmt->qmt_stopping) + RETURN(0); + if (strnlen(poolname, LOV_MAXPOOLNAME + 1) > LOV_MAXPOOLNAME) RETURN(-ENAMETOOLONG);