X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;ds=sidebyside;f=lustre%2Fmgc%2Fmgc_request.c;h=270de52d2aad5ca6943a8f9a818054bb0a7c337b;hb=f10069d3205cfab51f8ffa7a0a64bbcfcbb99320;hp=e3859319d0e59757be01103dc4a4f7c3c49d3570;hpb=6869932b552ac705f411de3362f01bd50c1f6f7d;p=fs%2Flustre-release.git diff --git a/lustre/mgc/mgc_request.c b/lustre/mgc/mgc_request.c index e385931..270de52 100644 --- a/lustre/mgc/mgc_request.c +++ b/lustre/mgc/mgc_request.c @@ -126,28 +126,42 @@ static int config_log_get(struct config_llog_data *cld) static void config_log_put(struct config_llog_data *cld) { ENTRY; + CDEBUG(D_INFO, "log %s refs %d\n", cld->cld_logname, atomic_read(&cld->cld_refcount)); - if (atomic_dec_and_test(&cld->cld_refcount)) { - CDEBUG(D_MGC, "dropping config log %s\n", cld->cld_logname); - class_export_put(cld->cld_mgcexp); - spin_lock(&config_list_lock); + LASSERT(atomic_read(&cld->cld_refcount) > 0); + + /* spinlock to make sure no item with 0 refcount in the list */ + spin_lock(&config_list_lock); + if (unlikely(atomic_dec_and_test(&cld->cld_refcount))) { list_del(&cld->cld_list_chain); spin_unlock(&config_list_lock); + + CDEBUG(D_MGC, "dropping config log %s\n", cld->cld_logname); + + if (cld->cld_sptlrpc) + config_log_put(cld->cld_sptlrpc); + if (cld->cld_is_sptlrpc) + sptlrpc_conf_log_stop(cld->cld_logname); + + class_export_put(cld->cld_mgcexp); OBD_FREE(cld->cld_logname, strlen(cld->cld_logname) + 1); if (cld->cld_cfg.cfg_instance != NULL) OBD_FREE(cld->cld_cfg.cfg_instance, strlen(cld->cld_cfg.cfg_instance) + 1); OBD_FREE(cld, sizeof(*cld)); + } else { + spin_unlock(&config_list_lock); } + EXIT; } /* Find a config log by name */ -static struct config_llog_data *config_log_find(char *logname, - struct config_llog_instance *cfg) +static +struct config_llog_data *config_log_find(char *logname, + struct config_llog_instance *cfg) { - struct list_head *tmp; struct config_llog_data *cld; char *logid = logname; int match_instance = 0; @@ -163,8 +177,7 @@ static struct config_llog_data *config_log_find(char *logname, } spin_lock(&config_list_lock); - list_for_each(tmp, &config_llog_list) { - cld = list_entry(tmp, struct config_llog_data, cld_list_chain); + list_for_each_entry(cld, &config_llog_list, cld_list_chain) { if (match_instance && cld->cld_cfg.cfg_instance && strcmp(logid, cld->cld_cfg.cfg_instance) == 0) goto out_found; @@ -179,74 +192,169 @@ static struct config_llog_data *config_log_find(char *logname, out_found: atomic_inc(&cld->cld_refcount); spin_unlock(&config_list_lock); + LASSERT(cld->cld_stopping == 0 || cld->cld_is_sptlrpc == 0); RETURN(cld); } -/* Add this log to our list of active logs. - We have one active log per "mount" - client instance or servername. - Each instance may be at a different point in the log. */ -static int config_log_add(char *logname, struct config_llog_instance *cfg, - struct super_block *sb) +static +struct config_llog_data *do_config_log_add(struct obd_device *obd, + char *logname, + unsigned int is_sptlrpc, + struct config_llog_instance *cfg, + struct super_block *sb) { struct config_llog_data *cld; - struct lustre_sb_info *lsi = s2lsi(sb); - int rc; + int rc; ENTRY; - CDEBUG(D_MGC, "adding config log %s:%s\n", logname, cfg->cfg_instance); + CDEBUG(D_MGC, "do adding config log %s:%s\n", logname, + cfg ? cfg->cfg_instance : "NULL"); OBD_ALLOC(cld, sizeof(*cld)); if (!cld) - RETURN(-ENOMEM); + RETURN(ERR_PTR(-ENOMEM)); OBD_ALLOC(cld->cld_logname, strlen(logname) + 1); if (!cld->cld_logname) { OBD_FREE(cld, sizeof(*cld)); - RETURN(-ENOMEM); + RETURN(ERR_PTR(-ENOMEM)); } strcpy(cld->cld_logname, logname); - cld->cld_cfg = *cfg; + if (cfg) + cld->cld_cfg = *cfg; cld->cld_cfg.cfg_last_idx = 0; cld->cld_cfg.cfg_flags = 0; cld->cld_cfg.cfg_sb = sb; + cld->cld_is_sptlrpc = is_sptlrpc; atomic_set(&cld->cld_refcount, 1); /* Keep the mgc around until we are done */ - cld->cld_mgcexp = class_export_get(lsi->lsi_mgc->obd_self_export); + cld->cld_mgcexp = class_export_get(obd->obd_self_export); - if (cfg->cfg_instance != NULL) { + if (cfg && cfg->cfg_instance != NULL) { OBD_ALLOC(cld->cld_cfg.cfg_instance, strlen(cfg->cfg_instance) + 1); strcpy(cld->cld_cfg.cfg_instance, cfg->cfg_instance); } + + if (is_sptlrpc) { + sptlrpc_conf_log_start(logname); + cld->cld_cfg.cfg_obdname = obd->obd_name; + } + rc = mgc_logname2resid(logname, &cld->cld_resid); + spin_lock(&config_list_lock); list_add(&cld->cld_list_chain, &config_llog_list); spin_unlock(&config_list_lock); - + if (rc) { config_log_put(cld); - RETURN(rc); + RETURN(ERR_PTR(rc)); } - RETURN(rc); + if (is_sptlrpc) { + rc = mgc_process_log(obd, cld); + if (rc) + CERROR("failed processing sptlrpc log: %d\n", rc); + } + + RETURN(cld); +} + +/** + * Add this log to our list of active logs. + * We have one active log per "mount" - client instance or servername. + * Each instance may be at a different point in the log. + */ +static int config_log_add(struct obd_device *obd, char *logname, + struct config_llog_instance *cfg, + struct super_block *sb) +{ + struct config_llog_data *cld, *sptlrpc_cld; + char seclogname[20]; + char *ptr; + ENTRY; + + CDEBUG(D_MGC, "adding config log %s:%s\n", logname, cfg->cfg_instance); + + /* + * for each regular log, the depended sptlrpc log name is + * -sptlrpc. multiple regular logs may share one sptlrpc log. + */ + ptr = strrchr(logname, '-'); + if (ptr == NULL || ptr - logname > 8) { + CERROR("logname %s is too long\n", logname); + RETURN(-EINVAL); + } + + memcpy(seclogname, logname, ptr - logname); + strcpy(seclogname + (ptr - logname), "-sptlrpc"); + + sptlrpc_cld = config_log_find(seclogname, NULL); + if (IS_ERR(sptlrpc_cld)) { + sptlrpc_cld = do_config_log_add(obd, seclogname, 1, NULL, NULL); + if (IS_ERR(sptlrpc_cld)) { + CERROR("can't create sptlrpc log: %s\n", seclogname); + RETURN(PTR_ERR(sptlrpc_cld)); + } + } + + cld = do_config_log_add(obd, logname, 0, cfg, sb); + if (IS_ERR(cld)) { + CERROR("can't create log: %s\n", logname); + config_log_put(sptlrpc_cld); + RETURN(PTR_ERR(cld)); + } + + cld->cld_sptlrpc = sptlrpc_cld; + + RETURN(0); } +DECLARE_MUTEX(llog_process_lock); + /* Stop watching for updates on this log. */ static int config_log_end(char *logname, struct config_llog_instance *cfg) { - struct config_llog_data *cld; + struct config_llog_data *cld, *cld_sptlrpc = NULL; int rc = 0; ENTRY; cld = config_log_find(logname, cfg); if (IS_ERR(cld)) RETURN(PTR_ERR(cld)); - /* drop the ref from the find */ - config_log_put(cld); + + down(&llog_process_lock); + /* + * if cld_stopping is set, it means we didn't start the log thus + * not owning the start ref. this can happen after previous umount: + * the cld still hanging there waiting for lock cancel, and we + * remount again but failed in the middle and call log_end without + * calling start_log. + */ + if (unlikely(cld->cld_stopping)) { + up(&llog_process_lock); + /* drop the ref from the find */ + config_log_put(cld); + RETURN(rc); + } cld->cld_stopping = 1; + up(&llog_process_lock); + + spin_lock(&config_list_lock); + cld_sptlrpc = cld->cld_sptlrpc; + cld->cld_sptlrpc = NULL; + spin_unlock(&config_list_lock); + + if (cld_sptlrpc) + config_log_put(cld_sptlrpc); + + /* drop the ref from the find */ + config_log_put(cld); /* drop the start ref */ config_log_put(cld); + CDEBUG(D_MGC, "end config log %s (%d)\n", logname ? logname : "client", rc); RETURN(rc); @@ -260,20 +368,35 @@ static int config_log_end(char *logname, struct config_llog_instance *cfg) static int rq_state = 0; static cfs_waitq_t rq_waitq; -static int mgc_process_log(struct obd_device *mgc, - struct config_llog_data *cld); static int mgc_requeue_add(struct config_llog_data *cld, int later); +static void do_requeue(struct config_llog_data *cld) +{ + LASSERT(atomic_read(&cld->cld_refcount) > 0); + + if (cld->cld_mgcexp->exp_obd->u.cli.cl_conn_count != 0) { + CDEBUG(D_MGC, "updating log %s\n", cld->cld_logname); + mgc_process_log(cld->cld_mgcexp->exp_obd, cld); + } else { + CDEBUG(D_MGC, "disconnecting, won't update log %s\n", + cld->cld_logname); + } + + /* Whether we enqueued again or not in mgc_process_log, we're done + * with the ref from the old enqueue */ + config_log_put(cld); +} + static int mgc_requeue_thread(void *data) { struct l_wait_info lwi_now, lwi_later; - struct config_llog_data *cld, *n; + struct config_llog_data *cld, *cld_next, *cld_prev; char name[] = "ll_cfg_requeue"; int rc = 0; ENTRY; ptlrpc_daemonize(name); - + CDEBUG(D_MGC, "Starting requeue thread\n"); lwi_later = LWI_TIMEOUT(60 * HZ, NULL, NULL); @@ -283,35 +406,65 @@ static int mgc_requeue_thread(void *data) spin_lock(&config_list_lock); while (rq_state & (RQ_NOW | RQ_LATER)) { /* Any new or requeued lostlocks will change the state */ - rq_state &= ~(RQ_NOW | RQ_LATER); + rq_state &= ~(RQ_NOW | RQ_LATER); spin_unlock(&config_list_lock); - /* Always wait a few seconds to allow the server who + /* Always wait a few seconds to allow the server who caused the lock revocation to finish its setup, plus some random so everyone doesn't try to reconnect at once. */ lwi_now = LWI_TIMEOUT(3 * HZ + (ll_rand() & 0xff) * (HZ / 100), NULL, NULL); l_wait_event(rq_waitq, rq_state & RQ_STOP, &lwi_now); - + + /* + * iterate & processing through the list. for each cld, process + * its depending sptlrpc cld firstly (if any) and then itself. + * + * it's guaranteed any item in the list must have + * reference > 0; and if cld_lostlock is set, at + * least one reference is taken by the previous enqueue. + * + * Note: releasing a cld might lead to itself and its depended + * sptlrpc cld be unlinked from the list. to safely iterate + * we need to take a reference on next cld before processing. + */ + cld_prev = NULL; + spin_lock(&config_list_lock); - list_for_each_entry_safe(cld, n, &config_llog_list, + list_for_each_entry_safe(cld, cld_next, &config_llog_list, cld_list_chain) { - spin_unlock(&config_list_lock); + if (cld->cld_list_chain.next != &config_llog_list) + atomic_inc(&cld_next->cld_refcount); + if (cld->cld_lostlock) { - CDEBUG(D_MGC, "updating log %s\n", - cld->cld_logname); + if (cld->cld_sptlrpc && + cld->cld_sptlrpc->cld_lostlock) { + cld->cld_sptlrpc->cld_lostlock = 0; + + spin_unlock(&config_list_lock); + do_requeue(cld->cld_sptlrpc); + spin_lock(&config_list_lock); + LASSERT(cld->cld_lostlock); + } + cld->cld_lostlock = 0; - rc = mgc_process_log(cld->cld_mgcexp->exp_obd, - cld); - /* Whether we enqueued again or not in - mgc_process_log, we're done with the ref - from the old enqueue */ - config_log_put(cld); + + spin_unlock(&config_list_lock); + do_requeue(cld); + spin_lock(&config_list_lock); } - spin_lock(&config_list_lock); + + + if (cld_prev) { + spin_unlock(&config_list_lock); + config_log_put(cld_prev); + spin_lock(&config_list_lock); + } + + cld_prev = cld_next; } spin_unlock(&config_list_lock); - + /* Wait a bit to see if anyone else needs a requeue */ l_wait_event(rq_waitq, rq_state & (RQ_NOW | RQ_STOP), &lwi_later); @@ -320,7 +473,7 @@ static int mgc_requeue_thread(void *data) /* spinlock and while guarantee RQ_NOW and RQ_LATER are not set */ rq_state &= ~RQ_RUNNING; spin_unlock(&config_list_lock); - + CDEBUG(D_MGC, "Ending requeue thread\n"); RETURN(rc); } @@ -331,20 +484,23 @@ static int mgc_requeue_add(struct config_llog_data *cld, int later) { int rc = 0; - CDEBUG(D_INFO, "log %s: requeue (l=%d r=%d sp=%d st=%x)\n", + CDEBUG(D_INFO, "log %s: requeue (l=%d r=%d sp=%d st=%x)\n", cld->cld_logname, later, atomic_read(&cld->cld_refcount), cld->cld_stopping, rq_state); + LASSERT(atomic_read(&cld->cld_refcount) > 0); /* Hold lock for rq_state */ spin_lock(&config_list_lock); - cld->cld_lostlock = 1; if (cld->cld_stopping || (rq_state & RQ_STOP)) { + cld->cld_lostlock = 0; spin_unlock(&config_list_lock); config_log_put(cld); RETURN(0); } + cld->cld_lostlock = 1; + if (!(rq_state & RQ_RUNNING)) { LASSERT(rq_state == 0); rq_state = RQ_RUNNING | (later ? RQ_LATER : RQ_NOW); @@ -420,7 +576,7 @@ static int mgc_fs_setup(struct obd_device *obd, struct super_block *sb, /* We take an obd ref to insure that we can't get to mgc_cleanup without calling mgc_fs_cleanup first. */ - class_incref(obd); + class_incref(obd, "mgc_fs", obd); label = fsfilt_get_label(obd, mnt->mnt_sb); if (label) @@ -451,7 +607,7 @@ static int mgc_fs_cleanup(struct obd_device *obd) l_dput(cli->cl_mgc_configs_dir); cli->cl_mgc_configs_dir = NULL; pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); - class_decref(obd); + class_decref(obd, "mgc_fs", obd); } cli->cl_mgc_vfsmnt = NULL; @@ -474,7 +630,7 @@ static int mgc_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage) break; case OBD_CLEANUP_EXPORTS: if (atomic_dec_and_test(&mgc_count)) { - /* Kick the requeue waitq - cld's should all be + /* Kick the requeue waitq - cld's should all be stopping */ spin_lock(&config_list_lock); rq_state |= RQ_STOP; @@ -530,6 +686,7 @@ static int mgc_setup(struct obd_device *obd, struct lustre_cfg *lcfg) lprocfs_mgc_init_vars(&lvars); lprocfs_obd_setup(obd, lvars.obd_vars); + sptlrpc_lprocfs_cliobd_attach(obd); spin_lock(&config_list_lock); atomic_inc(&mgc_count); @@ -578,9 +735,9 @@ static int mgc_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, } /* Are we done with this log? */ if (cld->cld_stopping) { - CDEBUG(D_MGC, "log %s: stopping, won't requeue\n", + CDEBUG(D_MGC, "log %s: stopping, won't requeue\n", cld->cld_logname); - config_log_put(cld); + config_log_put(cld); break; } /* Make sure not to re-enqueue when the mgc is stopping @@ -589,11 +746,12 @@ static int mgc_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, !lock->l_conn_export->exp_obd->u.cli.cl_conn_count) { CDEBUG(D_MGC, "log %s: disconnecting, won't requeue\n", cld->cld_logname); - config_log_put(cld); + config_log_put(cld); break; } /* Did we fail to get the lock? */ - if (lock->l_req_mode != lock->l_granted_mode) { + if (lock->l_req_mode != lock->l_granted_mode && + !cld->cld_is_sptlrpc) { CDEBUG(D_MGC, "log %s: original grant failed, will " "requeue later\n", cld->cld_logname); /* Try to re-enqueue later */ @@ -634,11 +792,14 @@ static int mgc_set_mgs_param(struct obd_export *exp, RETURN(-ENOMEM); req_msp = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*req_msp)); - if (!req_msp) + if (!req_msp) { + ptlrpc_req_finished(req); RETURN(-ENOMEM); + } memcpy(req_msp, msp, sizeof(*req_msp)); ptlrpc_req_set_repsize(req, 2, rep_size); + rc = ptlrpc_queue_wait(req); if (!rc) { rep_msp = lustre_swab_repbuf(req, REPLY_REC_OFF, @@ -660,7 +821,7 @@ static int mgc_enqueue(struct obd_export *exp, struct lov_stripe_md *lsm, { struct config_llog_data *cld = (struct config_llog_data *)data; struct ldlm_enqueue_info einfo = { type, mode, mgc_blocking_ast, - ldlm_completion_ast, NULL, data}; + ldlm_completion_ast, NULL, NULL, data}; int rc; ENTRY; @@ -677,8 +838,8 @@ static int mgc_enqueue(struct obd_export *exp, struct lov_stripe_md *lsm, rc = ldlm_cli_enqueue(exp, NULL, &einfo, &cld->cld_resid, NULL, flags, NULL, 0, NULL, lockh, 0); - /* A failed enqueue should still call the mgc_blocking_ast, - where it will be requeued if needed ("grant failed"). */ + /* A failed enqueue should still call the mgc_blocking_ast, + where it will be requeued if needed ("grant failed"). */ RETURN(rc); } @@ -763,10 +924,13 @@ static int mgc_target_register(struct obd_export *exp, RETURN(-ENOMEM); req_mti = req_capsule_client_get(&req->rq_pill, &RMF_MGS_TARGET_INFO); - memcpy(req_mti, mti, sizeof(*req_mti)); + if (!req_mti) { + ptlrpc_req_finished(req); + RETURN(-ENOMEM); + } + memcpy(req_mti, mti, sizeof(*req_mti)); ptlrpc_request_set_replen(req); - CDEBUG(D_MGC, "register %s\n", mti->mti_svname); rc = ptlrpc_queue_wait(req); @@ -862,6 +1026,49 @@ int mgc_set_info_async(struct obd_export *exp, obd_count keylen, rc = mgc_set_mgs_param(exp, msp); RETURN(rc); } + if (KEY_IS(KEY_MGSSEC)) { + struct client_obd *cli = &exp->exp_obd->u.cli; + struct sptlrpc_flavor flvr; + + /* + * empty string means using current flavor, if which haven't + * been set yet, set it as null. + * + * if flavor has been set previously, check the asking flavor + * must match the existing one. + */ + if (vallen == 0) { + if (cli->cl_flvr_mgc.sf_rpc != SPTLRPC_FLVR_INVALID) + RETURN(0); + val = "null"; + vallen = 4; + } + + rc = sptlrpc_parse_flavor(val, &flvr); + if (rc) { + CERROR("invalid sptlrpc flavor %s to MGS\n", + (char *) val); + RETURN(rc); + } + + /* + * caller already hold a mutex + */ + if (cli->cl_flvr_mgc.sf_rpc == SPTLRPC_FLVR_INVALID) { + cli->cl_flvr_mgc = flvr; + } else if (memcmp(&cli->cl_flvr_mgc, &flvr, + sizeof(flvr)) != 0) { + char str[20]; + + sptlrpc_flavor2name(&cli->cl_flvr_mgc, + str, sizeof(str)); + LCONSOLE_ERROR("asking sptlrpc flavor %s to MGS but " + "currently %s is in use\n", + (char *) val, str); + rc = -EPERM; + } + RETURN(rc); + } RETURN(rc); } @@ -889,7 +1096,7 @@ static int mgc_import_event(struct obd_device *obd, case IMP_EVENT_ACTIVE: LCONSOLE_WARN("%s: Reactivating import\n", obd->obd_name); /* Clearing obd_no_recov allows us to continue pinging */ - obd->obd_no_recov = 0; + obd->obd_no_recov = 0; break; case IMP_EVENT_OCD: break; @@ -919,8 +1126,18 @@ static int mgc_llog_init(struct obd_device *obd, struct obd_llog_group *olg, &llog_client_ops); if (rc == 0) { ctxt = llog_get_context(obd, LLOG_CONFIG_REPL_CTXT); + if (!ctxt) { + ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT); + if (ctxt) + llog_cleanup(ctxt); + RETURN(-ENODEV); + } llog_initiator_connect(ctxt); llog_ctxt_put(ctxt); + } else { + ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT); + if (ctxt) + llog_cleanup(ctxt); } RETURN(rc); @@ -1003,7 +1220,7 @@ static int mgc_copy_llog(struct obd_device *obd, struct llog_ctxt *rctxt, upon successful completion. */ OBD_ALLOC(temp_log, strlen(logname) + 1); - if (!temp_log) + if (!temp_log) RETURN(-ENOMEM); sprintf(temp_log, "%sT", logname); @@ -1012,7 +1229,7 @@ static int mgc_copy_llog(struct obd_device *obd, struct llog_ctxt *rctxt, if (rc) GOTO(out, rc); rc = llog_init_handle(local_llh, LLOG_F_IS_PLAIN, NULL); - if (rc) + if (rc) GOTO(out, rc); rc = llog_destroy(local_llh); llog_free_handle(local_llh); @@ -1069,32 +1286,36 @@ out: RETURN(rc); } -DECLARE_MUTEX(llog_process_lock); - /* Get a config log from the MGS and process it. This func is called for both clients and servers. */ -static int mgc_process_log(struct obd_device *mgc, - struct config_llog_data *cld) +int mgc_process_log(struct obd_device *mgc, + struct config_llog_data *cld) { struct llog_ctxt *ctxt, *lctxt; struct lustre_handle lockh; struct client_obd *cli = &mgc->u.cli; struct lvfs_run_ctxt saved; - struct lustre_sb_info *lsi; + struct lustre_sb_info *lsi = NULL; int rc = 0, rcl, flags = 0, must_pop = 0; ENTRY; - if (!cld || !cld->cld_cfg.cfg_sb) { - /* This should never happen */ - CERROR("Missing cld, aborting log update\n"); - RETURN(-EINVAL); - } - if (cld->cld_stopping) + LASSERT(cld); + + /* I don't want mutliple processes running process_log at once -- + sounds like badness. It actually might be fine, as long as + we're not trying to update from the same log + simultaneously (in which case we should use a per-log sem.) */ + down(&llog_process_lock); + + if (cld->cld_stopping) { + up(&llog_process_lock); RETURN(0); + } OBD_FAIL_TIMEOUT(OBD_FAIL_MGC_PAUSE_PROCESS_LOG, 20); - lsi = s2lsi(cld->cld_cfg.cfg_sb); + if (cld->cld_cfg.cfg_sb) + lsi = s2lsi(cld->cld_cfg.cfg_sb); CDEBUG(D_MGC, "Process log %s:%s from %d\n", cld->cld_logname, cld->cld_cfg.cfg_instance, cld->cld_cfg.cfg_last_idx + 1); @@ -1102,15 +1323,10 @@ static int mgc_process_log(struct obd_device *mgc, ctxt = llog_get_context(mgc, LLOG_CONFIG_REPL_CTXT); if (!ctxt) { CERROR("missing llog context\n"); + up(&llog_process_lock); RETURN(-EINVAL); } - /* I don't want mutliple processes running process_log at once -- - sounds like badness. It actually might be fine, as long as - we're not trying to update from the same log - simultaneously (in which case we should use a per-log sem.) */ - down(&llog_process_lock); - /* Get the cfg lock on the llog */ rcl = mgc_enqueue(mgc->u.cli.cl_mgc_mgsexp, NULL, LDLM_PLAIN, NULL, LCK_CR, &flags, NULL, NULL, NULL, @@ -1120,6 +1336,13 @@ static int mgc_process_log(struct obd_device *mgc, lctxt = llog_get_context(mgc, LLOG_CONFIG_ORIG_CTXT); + /* + * local copy of sptlrpc log is controlled elsewhere, don't try to + * read it up here. + */ + if (rcl && cld->cld_is_sptlrpc) + goto out_pop; + /* Copy the setup log locally if we can. Don't mess around if we're running an MGS though (logs are already local). */ if (lctxt && lsi && (lsi->lsi_flags & LSI_SERVER) && @@ -1138,7 +1361,7 @@ static int mgc_process_log(struct obd_device *mgc, GOTO(out_pop, rc = -ENOTCONN); } CDEBUG(D_MGC, "Failed to get MGS log %s, using local " - "copy for now, will try to update later.\n", + "copy for now, will try to update later.\n", cld->cld_logname); } /* Now, whether we copied or not, start using the local llog. @@ -1148,6 +1371,9 @@ static int mgc_process_log(struct obd_device *mgc, ctxt = lctxt; } + if (cld->cld_is_sptlrpc) + sptlrpc_conf_log_update_begin(cld->cld_logname); + /* logname and instance info should be the same, so use our copy of the instance for the update. The cfg_last_idx will be updated here. */ @@ -1159,6 +1385,19 @@ out_pop: if (must_pop) pop_ctxt(&saved, &mgc->obd_lvfs_ctxt, NULL); + /* + * update settings on existing OBDs. doing it inside + * of llog_process_lock so no device is attaching/detaching + * in parallel. + * the logname must be -sptlrpc + */ + if (cld->cld_is_sptlrpc && rcl == 0) { + sptlrpc_conf_log_update_end(cld->cld_logname); + class_notify_sptlrpc_conf(cld->cld_logname, + strlen(cld->cld_logname) - + strlen("-sptlrpc")); + } + /* Now drop the lock so MGS can revoke it */ if (!rcl) { rcl = mgc_cancel(mgc->u.cli.cl_mgc_mgsexp, NULL, @@ -1203,6 +1442,10 @@ static int mgc_process_config(struct obd_device *obd, obd_count len, void *buf) CERROR("lov_del_obd unimplemented\n"); rc = -ENOSYS; break; + case LCFG_SPTLRPC_CONF: { + rc = sptlrpc_process_config(lcfg); + break; + } case LCFG_LOG_START: { struct config_llog_data *cld; struct config_llog_instance *cfg; @@ -1215,7 +1458,7 @@ static int mgc_process_config(struct obd_device *obd, obd_count len, void *buf) cfg->cfg_last_idx); /* We're only called through here on the initial mount */ - rc = config_log_add(logname, cfg, sb); + rc = config_log_add(obd, logname, cfg, sb); if (rc) break; cld = config_log_find(logname, cfg);