X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fmgc%2Fmgc_request.c;h=18c2106e757f8540fc5c2d95388bc3710bdef7e9;hb=bcd9aefd57384fe1e3d569049d29c6d633451de7;hp=2ab2ef3e3fe75261fd18094b3dd8afbd589780c1;hpb=9edebe083264464d2692da446f68483e3e45a80d;p=fs%2Flustre-release.git diff --git a/lustre/mgc/mgc_request.c b/lustre/mgc/mgc_request.c index 2ab2ef3..18c2106 100644 --- a/lustre/mgc/mgc_request.c +++ b/lustre/mgc/mgc_request.c @@ -26,7 +26,7 @@ * GPL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. */ /* @@ -107,7 +107,7 @@ int mgc_logname2resid(char *logname, struct ldlm_res_id *res_id) /********************** config llog list **********************/ static CFS_LIST_HEAD(config_llog_list); -static spinlock_t config_list_lock = SPIN_LOCK_UNLOCKED; +static cfs_spinlock_t config_list_lock = CFS_SPIN_LOCK_UNLOCKED; /* Take a reference to a config log */ static int config_log_get(struct config_llog_data *cld) @@ -115,9 +115,9 @@ static int config_log_get(struct config_llog_data *cld) ENTRY; if (cld->cld_stopping) RETURN(1); - atomic_inc(&cld->cld_refcount); + cfs_atomic_inc(&cld->cld_refcount); CDEBUG(D_INFO, "log %s refs %d\n", cld->cld_logname, - atomic_read(&cld->cld_refcount)); + cfs_atomic_read(&cld->cld_refcount)); RETURN(0); } @@ -128,14 +128,14 @@ 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)); - LASSERT(atomic_read(&cld->cld_refcount) > 0); + cfs_atomic_read(&cld->cld_refcount)); + LASSERT(cfs_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); + cfs_spin_lock(&config_list_lock); + if (unlikely(cfs_atomic_dec_and_test(&cld->cld_refcount))) { + cfs_list_del(&cld->cld_list_chain); + cfs_spin_unlock(&config_list_lock); CDEBUG(D_MGC, "dropping config log %s\n", cld->cld_logname); @@ -151,7 +151,7 @@ static void config_log_put(struct config_llog_data *cld) strlen(cld->cld_cfg.cfg_instance) + 1); OBD_FREE(cld, sizeof(*cld)); } else { - spin_unlock(&config_list_lock); + cfs_spin_unlock(&config_list_lock); } EXIT; @@ -176,8 +176,8 @@ struct config_llog_data *config_log_find(char *logname, RETURN(ERR_PTR(-EINVAL)); } - spin_lock(&config_list_lock); - list_for_each_entry(cld, &config_llog_list, cld_list_chain) { + cfs_spin_lock(&config_list_lock); + cfs_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; @@ -185,13 +185,13 @@ struct config_llog_data *config_log_find(char *logname, strcmp(logid, cld->cld_logname) == 0) goto out_found; } - spin_unlock(&config_list_lock); + cfs_spin_unlock(&config_list_lock); CDEBUG(D_CONFIG, "can't get log %s\n", logid); RETURN(ERR_PTR(-ENOENT)); out_found: - atomic_inc(&cld->cld_refcount); - spin_unlock(&config_list_lock); + cfs_atomic_inc(&cld->cld_refcount); + cfs_spin_unlock(&config_list_lock); LASSERT(cld->cld_stopping == 0 || cld->cld_is_sptlrpc == 0); RETURN(cld); } @@ -221,11 +221,12 @@ struct config_llog_data *do_config_log_add(struct obd_device *obd, strcpy(cld->cld_logname, logname); if (cfg) cld->cld_cfg = *cfg; + cfs_mutex_init(&cld->cld_lock); 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); + cfs_atomic_set(&cld->cld_refcount, 1); /* Keep the mgc around until we are done */ cld->cld_mgcexp = class_export_get(obd->obd_self_export); @@ -243,9 +244,9 @@ struct config_llog_data *do_config_log_add(struct obd_device *obd, 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); + cfs_spin_lock(&config_list_lock); + cfs_list_add(&cld->cld_list_chain, &config_llog_list); + cfs_spin_unlock(&config_list_lock); if (rc) { config_log_put(cld); @@ -261,8 +262,8 @@ struct config_llog_data *do_config_log_add(struct obd_device *obd, RETURN(cld); } -/** - * Add this log to our list of active logs. +/** Add this log to the list of active logs watched by an MGC. + * Active means we're watching for updates. * We have one active log per "mount" - client instance or servername. * Each instance may be at a different point in the log. */ @@ -311,35 +312,51 @@ static int config_log_add(struct obd_device *obd, char *logname, RETURN(0); } -DECLARE_MUTEX(llog_process_lock); +CFS_DECLARE_MUTEX(llog_process_lock); -/* Stop watching for updates on this log. */ +/** Stop watching for updates on this log. + */ static int config_log_end(char *logname, struct config_llog_instance *cfg) { - struct config_llog_data *cld, *cld_sptlrpc; + 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); + cfs_mutex_lock(&cld->cld_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)) { + cfs_mutex_unlock(&cld->cld_lock); + /* drop the ref from the find */ + config_log_put(cld); + RETURN(rc); + } + cld->cld_stopping = 1; - up(&llog_process_lock); + cfs_mutex_unlock(&cld->cld_lock); - spin_lock(&config_list_lock); + cfs_spin_lock(&config_list_lock); cld_sptlrpc = cld->cld_sptlrpc; cld->cld_sptlrpc = NULL; - spin_unlock(&config_list_lock); + cfs_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); @@ -357,8 +374,12 @@ 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); + LASSERT(cfs_atomic_read(&cld->cld_refcount) > 0); + /* Do not run mgc_process_log on a disconnected export or an + export which is being disconnected. Take the client + semaphore to make the check non-racy. */ + cfs_down_read(&cld->cld_mgcexp->exp_obd->u.cli.cl_sem); 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); @@ -366,6 +387,7 @@ static void do_requeue(struct config_llog_data *cld) CDEBUG(D_MGC, "disconnecting, won't update log %s\n", cld->cld_logname); } + cfs_up_read(&cld->cld_mgcexp->exp_obd->u.cli.cl_sem); /* Whether we enqueued again or not in mgc_process_log, we're done * with the ref from the old enqueue */ @@ -380,24 +402,25 @@ static int mgc_requeue_thread(void *data) int rc = 0; ENTRY; - ptlrpc_daemonize(name); + cfs_daemonize(name); CDEBUG(D_MGC, "Starting requeue thread\n"); - lwi_later = LWI_TIMEOUT(60 * HZ, NULL, NULL); + lwi_later = LWI_TIMEOUT(60 * CFS_HZ, NULL, NULL); l_wait_event(rq_waitq, rq_state & (RQ_NOW | RQ_STOP), &lwi_later); /* Keep trying failed locks periodically */ - spin_lock(&config_list_lock); + cfs_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); - spin_unlock(&config_list_lock); + cfs_spin_unlock(&config_list_lock); /* 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), + lwi_now = LWI_TIMEOUT(3 * CFS_HZ + (cfs_rand() & 0xff) * \ + (CFS_HZ / 100), NULL, NULL); l_wait_event(rq_waitq, rq_state & RQ_STOP, &lwi_now); @@ -415,49 +438,49 @@ static int mgc_requeue_thread(void *data) */ cld_prev = NULL; - spin_lock(&config_list_lock); - list_for_each_entry_safe(cld, cld_next, &config_llog_list, - cld_list_chain) { + cfs_spin_lock(&config_list_lock); + cfs_list_for_each_entry_safe(cld, cld_next, &config_llog_list, + cld_list_chain) { if (cld->cld_list_chain.next != &config_llog_list) - atomic_inc(&cld_next->cld_refcount); + cfs_atomic_inc(&cld_next->cld_refcount); if (cld->cld_lostlock) { if (cld->cld_sptlrpc && cld->cld_sptlrpc->cld_lostlock) { cld->cld_sptlrpc->cld_lostlock = 0; - spin_unlock(&config_list_lock); + cfs_spin_unlock(&config_list_lock); do_requeue(cld->cld_sptlrpc); - spin_lock(&config_list_lock); + cfs_spin_lock(&config_list_lock); LASSERT(cld->cld_lostlock); } cld->cld_lostlock = 0; - spin_unlock(&config_list_lock); + cfs_spin_unlock(&config_list_lock); do_requeue(cld); - spin_lock(&config_list_lock); + cfs_spin_lock(&config_list_lock); } if (cld_prev) { - spin_unlock(&config_list_lock); + cfs_spin_unlock(&config_list_lock); config_log_put(cld_prev); - spin_lock(&config_list_lock); + cfs_spin_lock(&config_list_lock); } cld_prev = cld_next; } - spin_unlock(&config_list_lock); + cfs_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); - spin_lock(&config_list_lock); + cfs_spin_lock(&config_list_lock); } /* spinlock and while guarantee RQ_NOW and RQ_LATER are not set */ rq_state &= ~RQ_RUNNING; - spin_unlock(&config_list_lock); + cfs_spin_unlock(&config_list_lock); CDEBUG(D_MGC, "Ending requeue thread\n"); RETURN(rc); @@ -470,16 +493,16 @@ 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", - cld->cld_logname, later, atomic_read(&cld->cld_refcount), + cld->cld_logname, later, cfs_atomic_read(&cld->cld_refcount), cld->cld_stopping, rq_state); - LASSERT(atomic_read(&cld->cld_refcount) > 0); + LASSERT(cfs_atomic_read(&cld->cld_refcount) > 0); /* Hold lock for rq_state */ - spin_lock(&config_list_lock); + cfs_spin_lock(&config_list_lock); if (cld->cld_stopping || (rq_state & RQ_STOP)) { cld->cld_lostlock = 0; - spin_unlock(&config_list_lock); + cfs_spin_unlock(&config_list_lock); config_log_put(cld); RETURN(0); } @@ -489,7 +512,7 @@ static int mgc_requeue_add(struct config_llog_data *cld, int later) if (!(rq_state & RQ_RUNNING)) { LASSERT(rq_state == 0); rq_state = RQ_RUNNING | (later ? RQ_LATER : RQ_NOW); - spin_unlock(&config_list_lock); + cfs_spin_unlock(&config_list_lock); rc = cfs_kernel_thread(mgc_requeue_thread, 0, CLONE_VM | CLONE_FILES); if (rc < 0) { @@ -503,7 +526,7 @@ static int mgc_requeue_add(struct config_llog_data *cld, int later) } } else { rq_state |= later ? RQ_LATER : RQ_NOW; - spin_unlock(&config_list_lock); + cfs_spin_unlock(&config_list_lock); cfs_waitq_signal(&rq_waitq); } @@ -527,13 +550,13 @@ static int mgc_fs_setup(struct obd_device *obd, struct super_block *sb, LASSERT(lsi->lsi_srv_mnt == mnt); /* The mgc fs exclusion sem. Only one fs can be setup at a time. */ - down(&cli->cl_mgc_sem); + cfs_down(&cli->cl_mgc_sem); - cleanup_group_info(); + cfs_cleanup_group_info(); obd->obd_fsops = fsfilt_get_ops(MT_STR(lsi->lsi_ldd)); if (IS_ERR(obd->obd_fsops)) { - up(&cli->cl_mgc_sem); + cfs_up(&cli->cl_mgc_sem); CERROR("No fstype %s rc=%ld\n", MT_STR(lsi->lsi_ldd), PTR_ERR(obd->obd_fsops)); RETURN(PTR_ERR(obd->obd_fsops)); @@ -548,7 +571,7 @@ static int mgc_fs_setup(struct obd_device *obd, struct super_block *sb, obd->obd_lvfs_ctxt.fs = get_ds(); push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); - dentry = lookup_one_len(MOUNT_CONFIGS_DIR, current->fs->pwd, + dentry = lookup_one_len(MOUNT_CONFIGS_DIR, cfs_fs_pwd(current->fs), strlen(MOUNT_CONFIGS_DIR)); pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); if (IS_ERR(dentry)) { @@ -574,7 +597,7 @@ err_ops: fsfilt_put_ops(obd->obd_fsops); obd->obd_fsops = NULL; cli->cl_mgc_vfsmnt = NULL; - up(&cli->cl_mgc_sem); + cfs_up(&cli->cl_mgc_sem); RETURN(err); } @@ -599,12 +622,12 @@ static int mgc_fs_cleanup(struct obd_device *obd) if (obd->obd_fsops) fsfilt_put_ops(obd->obd_fsops); - up(&cli->cl_mgc_sem); + cfs_up(&cli->cl_mgc_sem); RETURN(rc); } -static atomic_t mgc_count = ATOMIC_INIT(0); +static cfs_atomic_t mgc_count = CFS_ATOMIC_INIT(0); static int mgc_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage) { int rc = 0; @@ -614,12 +637,12 @@ static int mgc_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage) case OBD_CLEANUP_EARLY: break; case OBD_CLEANUP_EXPORTS: - if (atomic_dec_and_test(&mgc_count)) { + if (cfs_atomic_dec_and_test(&mgc_count)) { /* Kick the requeue waitq - cld's should all be stopping */ - spin_lock(&config_list_lock); + cfs_spin_lock(&config_list_lock); rq_state |= RQ_STOP; - spin_unlock(&config_list_lock); + cfs_spin_unlock(&config_list_lock); cfs_waitq_signal(&rq_waitq); } rc = obd_llog_finish(obd, 0); @@ -663,7 +686,7 @@ static int mgc_setup(struct obd_device *obd, struct lustre_cfg *lcfg) if (rc) GOTO(err_decref, rc); - rc = obd_llog_init(obd, &obd->obd_olg, obd, 0, NULL, NULL); + rc = obd_llog_init(obd, &obd->obd_olg, obd, NULL); if (rc) { CERROR("failed to setup llogging subsystems\n"); GOTO(err_cleanup, rc); @@ -671,14 +694,15 @@ 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); - if (atomic_read(&mgc_count) == 1) { + cfs_spin_lock(&config_list_lock); + cfs_atomic_inc(&mgc_count); + if (cfs_atomic_read(&mgc_count) == 1) { rq_state &= ~RQ_STOP; cfs_waitq_init(&rq_waitq); } - spin_unlock(&config_list_lock); + cfs_spin_unlock(&config_list_lock); RETURN(rc); @@ -759,32 +783,40 @@ static int mgc_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, RETURN(rc); } +/* Not sure where this should go... */ +#define MGC_ENQUEUE_LIMIT 50 +#define MGC_TARGET_REG_LIMIT 10 +#define MGC_SEND_PARAM_LIMIT 10 + /* Send parameter to MGS*/ static int mgc_set_mgs_param(struct obd_export *exp, struct mgs_send_param *msp) { struct ptlrpc_request *req; struct mgs_send_param *req_msp, *rep_msp; - int size[] = { sizeof(struct ptlrpc_body), sizeof(*req_msp) }; - __u32 rep_size[] = { sizeof(struct ptlrpc_body), sizeof(*msp) }; int rc; ENTRY; - req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_MGS_VERSION, - MGS_SET_INFO, 2, size, NULL); + req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp), + &RQF_MGS_SET_INFO, LUSTRE_MGS_VERSION, + MGS_SET_INFO); if (!req) RETURN(-ENOMEM); - req_msp = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF, sizeof(*req_msp)); - if (!req_msp) + req_msp = req_capsule_client_get(&req->rq_pill, &RMF_MGS_SEND_PARAM); + if (!req_msp) { + ptlrpc_req_finished(req); RETURN(-ENOMEM); + } memcpy(req_msp, msp, sizeof(*req_msp)); - ptlrpc_req_set_repsize(req, 2, rep_size); + ptlrpc_request_set_replen(req); + + /* Limit how long we will wait for the enqueue to complete */ + req->rq_delay_limit = MGC_SEND_PARAM_LIMIT; rc = ptlrpc_queue_wait(req); if (!rc) { - rep_msp = lustre_swab_repbuf(req, REPLY_REC_OFF, - sizeof(*rep_msp), NULL); + rep_msp = req_capsule_server_get(&req->rq_pill, &RMF_MGS_SEND_PARAM); memcpy(msp, rep_msp, sizeof(*rep_msp)); } @@ -803,7 +835,8 @@ 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, NULL, data}; - + struct ptlrpc_request *req; + int short_limit = cld->cld_is_sptlrpc; int rc; ENTRY; @@ -816,12 +849,25 @@ static int mgc_enqueue(struct obd_export *exp, struct lov_stripe_md *lsm, /* We need a callback for every lockholder, so don't try to ldlm_lock_match (see rev 1.1.2.11.2.47) */ - - rc = ldlm_cli_enqueue(exp, NULL, &einfo, &cld->cld_resid, - NULL, flags, NULL, 0, NULL, lockh, 0); + req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp), + &RQF_LDLM_ENQUEUE, LUSTRE_DLM_VERSION, + LDLM_ENQUEUE); + if (req == NULL) + RETURN(-ENOMEM); + ptlrpc_request_set_replen(req); + /* check if this is server or client */ + if (cld->cld_cfg.cfg_sb) { + struct lustre_sb_info *lsi = s2lsi(cld->cld_cfg.cfg_sb); + if (lsi && (lsi->lsi_flags & LSI_SERVER)) + short_limit = 1; + } + /* Limit how long we will wait for the enqueue to complete */ + req->rq_delay_limit = short_limit ? 5 : MGC_ENQUEUE_LIMIT; + rc = ldlm_cli_enqueue(exp, &req, &einfo, &cld->cld_resid, NULL, flags, + NULL, 0, lockh, 0); /* A failed enqueue should still call the mgc_blocking_ast, where it will be requeued if needed ("grant failed"). */ - + ptlrpc_req_finished(req); RETURN(rc); } @@ -835,60 +881,6 @@ static int mgc_cancel(struct obd_export *exp, struct lov_stripe_md *md, RETURN(0); } -#if 0 -static int mgc_iocontrol(unsigned int cmd, struct obd_export *exp, int len, - void *karg, void *uarg) -{ - struct obd_device *obd = exp->exp_obd; - struct obd_ioctl_data *data = karg; - struct llog_ctxt *ctxt; - struct lvfs_run_ctxt saved; - int rc; - ENTRY; - - if (!try_module_get(THIS_MODULE)) { - CERROR("Can't get module. Is it alive?"); - return -EINVAL; - } - switch (cmd) { - /* REPLicator context */ - case OBD_IOC_PARSE: { - CERROR("MGC parsing llog %s\n", data->ioc_inlbuf1); - ctxt = llog_get_context(exp->exp_obd, LLOG_CONFIG_REPL_CTXT); - rc = class_config_parse_llog(ctxt, data->ioc_inlbuf1, NULL); - GOTO(out, rc); - } -#ifdef __KERNEL__ - case OBD_IOC_LLOG_INFO: - case OBD_IOC_LLOG_PRINT: { - ctxt = llog_get_context(obd, LLOG_CONFIG_REPL_CTXT); - rc = llog_ioctl(ctxt, cmd, data); - - GOTO(out, rc); - } -#endif - /* ORIGinator context */ - case OBD_IOC_DUMP_LOG: { - ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT); - push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); - rc = class_config_dump_llog(ctxt, data->ioc_inlbuf1, NULL); - pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL); - if (rc) - RETURN(rc); - - GOTO(out, rc); - } - default: - CERROR("mgc_ioctl(): unrecognised ioctl %#x\n", cmd); - GOTO(out, rc = -ENOTTY); - } -out: - module_put(THIS_MODULE); - - return rc; -} -#endif - /* Send target_reg message to MGS */ static int mgc_target_register(struct obd_export *exp, struct mgs_target_info *mti) @@ -905,11 +897,16 @@ 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); + /* Limit how long we will wait for the enqueue to complete */ + req->rq_delay_limit = MGC_TARGET_REG_LIMIT; rc = ptlrpc_queue_wait(req); if (!rc) { @@ -928,40 +925,24 @@ int mgc_set_info_async(struct obd_export *exp, obd_count keylen, void *key, obd_count vallen, void *val, struct ptlrpc_request_set *set) { - struct obd_import *imp = class_exp2cliimp(exp); int rc = -EINVAL; ENTRY; - /* Try to "recover" the initial connection; i.e. retry */ - if (KEY_IS(KEY_INIT_RECOV)) { - if (vallen != sizeof(int)) - RETURN(-EINVAL); - spin_lock(&imp->imp_lock); - imp->imp_initial_recov = *(int *)val; - spin_unlock(&imp->imp_lock); - CDEBUG(D_HA, "%s: set imp_initial_recov = %d\n", - exp->exp_obd->obd_name, imp->imp_initial_recov); - RETURN(0); - } /* Turn off initial_recov after we try all backup servers once */ if (KEY_IS(KEY_INIT_RECOV_BACKUP)) { + struct obd_import *imp = class_exp2cliimp(exp); int value; if (vallen != sizeof(int)) RETURN(-EINVAL); value = *(int *)val; - spin_lock(&imp->imp_lock); - imp->imp_initial_recov_bk = value > 0; - /* Even after the initial connection, give up all comms if - nobody answers the first time. */ - imp->imp_recon_bk = 1; - spin_unlock(&imp->imp_lock); - CDEBUG(D_MGC, "InitRecov %s %d/%d:d%d:i%d:r%d:or%d:%s\n", - imp->imp_obd->obd_name, value, imp->imp_initial_recov, + CDEBUG(D_MGC, "InitRecov %s %d/d%d:i%d:r%d:or%d:%s\n", + imp->imp_obd->obd_name, value, imp->imp_deactive, imp->imp_invalid, imp->imp_replayable, imp->imp_obd->obd_replayable, ptlrpc_import_state_name(imp->imp_state)); /* Resurrect if we previously died */ - if (imp->imp_invalid || value > 1) + if ((imp->imp_state != LUSTRE_IMP_FULL && + imp->imp_state != LUSTRE_IMP_NEW) || value > 1) ptlrpc_reconnect_import(imp); RETURN(0); } @@ -1004,6 +985,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); } @@ -1043,8 +1067,7 @@ static int mgc_import_event(struct obd_device *obd, } static int mgc_llog_init(struct obd_device *obd, struct obd_llog_group *olg, - struct obd_device *tgt, int count, - struct llog_catid *logid, struct obd_uuid *uuid) + struct obd_device *tgt, int *index) { struct llog_ctxt *ctxt; int rc; @@ -1061,6 +1084,12 @@ 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 { @@ -1215,8 +1244,10 @@ out: RETURN(rc); } -/* Get a config log from the MGS and process it. - This func is called for both clients and servers. */ +/** Get a config log from the MGS and process it. + * This func is called for both clients and servers. + * Copy the log locally before parsing it if appropriate (non-MGS server) + */ int mgc_process_log(struct obd_device *mgc, struct config_llog_data *cld) { @@ -1230,14 +1261,14 @@ int mgc_process_log(struct obd_device *mgc, LASSERT(cld); - /* I don't want mutliple processes running process_log at once -- + /* I don't want multiple 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); + cfs_mutex_lock(&cld->cld_lock); if (cld->cld_stopping) { - up(&llog_process_lock); + cfs_mutex_unlock(&cld->cld_lock); RETURN(0); } @@ -1252,7 +1283,7 @@ 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); + cfs_mutex_unlock(&cld->cld_lock); RETURN(-EINVAL); } @@ -1270,8 +1301,8 @@ int mgc_process_log(struct obd_device *mgc, * read it up here. */ if (rcl && cld->cld_is_sptlrpc) - goto out_pop; - + GOTO(out_pop, rc); + /* 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) && @@ -1306,7 +1337,8 @@ int mgc_process_log(struct obd_device *mgc, /* 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. */ - rc = class_config_parse_llog(ctxt, cld->cld_logname, &cld->cld_cfg); + if (rcl == 0 || lctxt == ctxt) + rc = class_config_parse_llog(ctxt, cld->cld_logname, &cld->cld_cfg); out_pop: llog_ctxt_put(ctxt); if (ctxt != lctxt) @@ -1338,11 +1370,15 @@ out_pop: CDEBUG(D_MGC, "%s: configuration from log '%s' %sed (%d).\n", mgc->obd_name, cld->cld_logname, rc ? "fail" : "succeed", rc); - up(&llog_process_lock); + cfs_mutex_unlock(&cld->cld_lock); RETURN(rc); } +/** Called from lustre_process_log. + * LCFG_LOG_START gets the config log from the MGS, processes it to start + * any services, and adds it to the list logs to watch (follow). + */ static int mgc_process_config(struct obd_device *obd, obd_count len, void *buf) { struct lustre_cfg *lcfg = buf; @@ -1352,7 +1388,7 @@ static int mgc_process_config(struct obd_device *obd, obd_count len, void *buf) switch(cmd = lcfg->lcfg_command) { case LCFG_LOV_ADD_OBD: { - /* Add any new target, not just osts */ + /* Overloading this cfg command: register a new target */ struct mgs_target_info *mti; if (LUSTRE_CFG_BUFLEN(lcfg, 1) != @@ -1366,8 +1402,7 @@ static int mgc_process_config(struct obd_device *obd, obd_count len, void *buf) break; } case LCFG_LOV_DEL_OBD: - /* Remove target from the fs? */ - /* FIXME */ + /* Unregister has no meaning at the moment. */ CERROR("lov_del_obd unimplemented\n"); rc = -ENOSYS; break;