int class_find_param(char *buf, char *key, char **valp);
int class_match_param(char *buf, char *key, char **valp);
int class_parse_nid(char *buf, lnet_nid_t *nid, char **endh);
+int do_lcfg(char *cfgname, lnet_nid_t nid, int cmd,
+ char *s1, char *s2, char *s3, char *s4);
+
/****************** User-settable parameter keys *********************/
#define CFG_F_START 0x01 /* Set when we start updating from a log */
#define CFG_F_MARKER 0x02 /* We are within a maker */
#define CFG_F_SKIP 0x04 /* We should ignore this cfg command */
-#define CFG_F_COMPAT146 0x08 /* Translation to new obd names required */
+#define CFG_F_COMPAT146 0x08 /* Using old-style log */
#define CFG_F_EXCLUDE 0x10 /* OST exclusion list */
struct lustre_profile *class_get_profile(char * prof);
void class_del_profile(char *prof);
+void class_del_profiles(void);
/* genops.c */
#define class_export_get(exp) \
#include <lustre_dlm.h>
#include <lprocfs_status.h>
#include <lustre_disk.h>
+#include <lustre_param.h>
#include "llite_internal.h"
kmem_cache_t *ll_file_data_slab;
INIT_LIST_HEAD(&lli->lli_dead_list);
}
+/* COMPAT_146 */
+#define MDCDEV "mdc_dev"
+static int old_lustre_process_log(struct super_block *sb, char *newprofile,
+ struct config_llog_instance *cfg)
+{
+ struct lustre_sb_info *lsi = s2lsi(sb);
+ struct obd_device *obd;
+ struct lustre_handle mdc_conn = {0, };
+ struct obd_export *exp;
+ char *ptr, *mdt, *profile;
+ char niduuid[10] = "mdtnid0";
+ class_uuid_t uuid;
+ struct obd_uuid mdc_uuid;
+ struct llog_ctxt *ctxt;
+ struct obd_connect_data ocd = { 0 };
+ lnet_nid_t nid;
+ int i, rc = 0, recov_bk = 1, failnodes = 0;
+ ENTRY;
+
+ class_generate_random_uuid(uuid);
+ class_uuid_unparse(uuid, &mdc_uuid);
+ CDEBUG(D_HA, "generated uuid: %s\n", mdc_uuid.uuid);
+
+ /* Figure out the old mdt and profile name from new-style profile
+ ("lustre" from "mds/lustre-client") */
+ mdt = newprofile;
+ profile = strchr(mdt, '/');
+ if (profile == NULL) {
+ CDEBUG(D_CONFIG, "Can't find MDT name in %s\n", newprofile);
+ GOTO(out, rc = -EINVAL);
+ }
+ *profile = '\0';
+ profile++;
+ ptr = strrchr(profile, '-');
+ if (ptr == NULL) {
+ CDEBUG(D_CONFIG, "Can't find client name in %s\n", newprofile);
+ GOTO(out, rc = -EINVAL);
+ }
+ *ptr = '\0';
+
+ LCONSOLE_WARN("This looks like an old mount command; I will try to "
+ "contact MDT '%s' for profile '%s'\n", mdt, profile);
+
+ /* Use nids from mount line: uml1,1@elan:uml2,2@elan:/lustre */
+ i = 0;
+ ptr = lsi->lsi_lmd->lmd_dev;
+ while (class_parse_nid(ptr, &nid, &ptr) == 0) {
+ rc = do_lcfg(MDCDEV, nid, LCFG_ADD_UUID, niduuid, 0,0,0);
+ i++;
+ /* Stop at the first failover nid */
+ if (*ptr == ':')
+ break;
+ }
+ if (i == 0) {
+ CERROR("No valid MDT nids found.\n");
+ GOTO(out, rc = -EINVAL);
+ }
+ failnodes++;
+
+ rc = do_lcfg(MDCDEV, 0, LCFG_ATTACH, LUSTRE_MDC_NAME,mdc_uuid.uuid,0,0);
+ if (rc < 0)
+ GOTO(out_del_uuid, rc);
+
+ rc = do_lcfg(MDCDEV, 0, LCFG_SETUP, mdt, niduuid, 0, 0);
+ if (rc < 0) {
+ LCONSOLE_ERROR("I couldn't establish a connection with the MDT."
+ " Check that the MDT host NID is correct and the"
+ " networks are up.\n");
+ GOTO(out_detach, rc);
+ }
+
+ obd = class_name2obd(MDCDEV);
+ if (obd == NULL)
+ GOTO(out_cleanup, rc = -EINVAL);
+
+ /* Add any failover nids */
+ while (*ptr == ':') {
+ /* New failover node */
+ sprintf(niduuid, "mdtnid%d", failnodes);
+ i = 0;
+ while (class_parse_nid(ptr, &nid, &ptr) == 0) {
+ i++;
+ rc = do_lcfg(MDCDEV, nid, LCFG_ADD_UUID, niduuid,0,0,0);
+ if (rc)
+ CERROR("Add uuid for %s failed %d\n",
+ libcfs_nid2str(nid), rc);
+ if (*ptr == ':')
+ break;
+ }
+ if (i > 0) {
+ rc = do_lcfg(MDCDEV, 0, LCFG_ADD_CONN, niduuid, 0, 0,0);
+ if (rc)
+ CERROR("Add conn for %s failed %d\n",
+ libcfs_nid2str(nid), rc);
+ failnodes++;
+ } else {
+ /* at ":/fsname" */
+ break;
+ }
+ }
+
+ /* Try all connections, but only once. */
+ rc = obd_set_info_async(obd->obd_self_export,
+ strlen("init_recov_bk"), "init_recov_bk",
+ sizeof(recov_bk), &recov_bk, NULL);
+ if (rc)
+ GOTO(out_cleanup, rc);
+
+ ocd.ocd_connect_flags = OBD_CONNECT_ACL;
+
+ rc = obd_connect(&mdc_conn, obd, &mdc_uuid, &ocd);
+ if (rc) {
+ CERROR("cannot connect to %s: rc = %d\n", mdt, rc);
+ GOTO(out_cleanup, rc);
+ }
+
+ exp = class_conn2export(&mdc_conn);
+
+ ctxt = llog_get_context(exp->exp_obd, LLOG_CONFIG_REPL_CTXT);
+
+ cfg->cfg_flags |= CFG_F_COMPAT146;
+
+#if 1
+ rc = class_config_parse_llog(ctxt, profile, cfg);
+#else
+ /*
+ * For debugging, it's useful to just dump the log
+ */
+ rc = class_config_dump_llog(ctxt, profile, cfg);
+#endif
+ switch (rc) {
+ case 0: {
+ /* Set the caller's profile name to the old-style */
+ memcpy(newprofile, profile, strlen(profile) + 1);
+ break;
+ }
+ case -EINVAL:
+ LCONSOLE_ERROR("%s: The configuration '%s' could not be read "
+ "from the MDT '%s'. Make sure this client and "
+ "the MDT are running compatible versions of "
+ "Lustre.\n",
+ obd->obd_name, profile, mdt);
+ /* fall through */
+ default:
+ LCONSOLE_ERROR("%s: The configuration '%s' could not be read "
+ "from the MDT '%s'. This may be the result of "
+ "communication errors between the client and "
+ "the MDT, or if the MDT is not running.\n",
+ obd->obd_name, profile, mdt);
+ break;
+ }
+
+ /* We don't so much care about errors in cleaning up the config llog
+ * connection, as we have already read the config by this point. */
+ obd_disconnect(exp);
+
+out_cleanup:
+ do_lcfg(MDCDEV, 0, LCFG_CLEANUP, 0, 0, 0, 0);
+
+out_detach:
+ do_lcfg(MDCDEV, 0, LCFG_DETACH, 0, 0, 0, 0);
+
+out_del_uuid:
+ /* class_add_uuid adds a nid even if the same uuid exists; we might
+ delete any copy here. So they all better match. */
+ for (i = 0; i < failnodes; i++) {
+ sprintf(niduuid, "mdtnid%d", i);
+ do_lcfg(MDCDEV, 0, LCFG_DEL_UUID, niduuid, 0, 0, 0);
+ }
+ /* class_import_put will get rid of the additional connections */
+out:
+ RETURN(rc);
+}
+/* end COMPAT_146 */
+
int ll_fill_super(struct super_block *sb)
{
struct lustre_profile *lprof;
struct lustre_sb_info *lsi = s2lsi(sb);
struct ll_sb_info *sbi;
- char *osc = NULL;
- char *mdc = NULL;
+ char *osc = NULL, *mdc = NULL;
char *profilenm = get_profile_name(sb);
struct config_llog_instance cfg;
char ll_instance[sizeof(sb) * 2 + 1];
/* set up client obds */
err = lustre_process_log(sb, profilenm, &cfg);
+ /* COMPAT_146 */
+ if (err < 0) {
+ char *oldname;
+ int rc, oldnamelen;
+ oldnamelen = strlen(profilenm) + 1;
+ /* Temp storage for 1.4.6 profile name */
+ OBD_ALLOC(oldname, oldnamelen);
+ if (oldname) {
+ memcpy(oldname, profilenm, oldnamelen);
+ rc = old_lustre_process_log(sb, oldname, &cfg);
+ if (rc >= 0) {
+ /* That worked - update the profile name
+ permanently */
+ err = rc;
+ OBD_FREE(lsi->lsi_lmd->lmd_profile,
+ strlen(lsi->lsi_lmd->lmd_profile) + 1);
+ OBD_ALLOC(lsi->lsi_lmd->lmd_profile,
+ strlen(oldname) + 1);
+ if (!lsi->lsi_lmd->lmd_profile) {
+ OBD_FREE(oldname, oldnamelen);
+ GOTO(out_free, err = -ENOMEM);
+ }
+ memcpy(lsi->lsi_lmd->lmd_profile, oldname,
+ strlen(oldname) + 1);
+ profilenm = get_profile_name(sb);
+ }
+ OBD_FREE(oldname, oldnamelen);
+ }
+ }
+ /* end COMPAT_146 */
if (err < 0) {
CERROR("Unable to process log: %d\n", err);
GOTO(out_free, err);
OBD_FREE(mdc, strlen(mdc) + 1);
if (osc)
OBD_FREE(osc, strlen(osc) + 1);
- if (err) {
- struct obd_device *obd;
- int next = 0;
- /* like ll_put_super below */
- lustre_end_log(sb, NULL, &cfg);
- while ((obd = class_devices_in_group(&sbi->ll_sb_uuid, &next))
- != NULL) {
- class_manual_cleanup(obd);
- }
- class_del_profile(profilenm);
- ll_free_sbi(sb);
- lsi->lsi_llsbi = NULL;
- lustre_common_put_super(sb);
- }
+ if (err)
+ ll_put_super(sb);
RETURN(err);
} /* ll_fill_super */
}
}
- client_common_put_super(sb);
+ if (sbi->ll_lcq)
+ /* Only call if client_common_fill_super succeeded */
+ client_common_put_super(sb);
next = 0;
while ((obd = class_devices_in_group(&sbi->ll_sb_uuid, &next)) !=NULL) {
obd_ioctl_freedata(buf, len);
return rc;
}
+
+
tgt->ltd_reap = 0;
lov->desc.ld_active_tgt_count++;
- rc = qos_add_tgt(obd, tgt);
- if (rc)
- CERROR("qos_add_tgt failed %d\n", rc);
-
#ifdef __KERNEL__
lov_proc_dir = lprocfs_srch(obd->obd_proc_entry, "target_obds");
if (lov_proc_dir) {
if (rc)
GOTO(out, rc);
+ rc = qos_add_tgt(obd, tgt);
+ if (rc)
+ CERROR("qos_add_tgt failed %d\n", rc);
+
idx = index;
rc = lov_notify(obd, tgt->ltd_exp->exp_obd,
active ? OBD_NOTIFY_ACTIVE : OBD_NOTIFY_INACTIVE,
atomic_set(&lov->lov_refcount, 0);
INIT_LIST_HEAD(&lov->lov_qos.lq_oss_list);
init_rwsem(&lov->lov_qos.lq_rw_sem);
+ lov->lov_qos.lq_dirty = 1;
+ lov->lov_qos.lq_dirty_rr = 1;
+ lov->lov_qos.lq_reset = 1;
lprocfs_init_vars(lov, &lvars);
lprocfs_obd_setup(obd, lvars.obd_vars);
int rc = 0, found = 0;
ENTRY;
- if (!obd->obd_observer)
- /* QOS is only on MDT, not clients */
- RETURN(0);
-
+ /* We only need this QOS struct on MDT, not clients - but we may not
+ have registered the lov's observer yet, so there's no way to check
+ here. */
+
if (!tgt->ltd_exp || !tgt->ltd_exp->exp_connection) {
CERROR("Missing connection\n");
RETURN(-ENOTCONN);
{
struct lov_qos_oss *oss;
struct lov_tgt_desc *tgt;
- unsigned ost_count;
+ unsigned ost_count, placed;
int i;
ENTRY;
lov->lov_qos.lq_rr_array[i] = LOV_QOS_EMPTY;
/* Place all the OSTs from 1 OSS at the same time. */
+ placed = 0;
list_for_each_entry(oss, &lov->lov_qos.lq_oss_list, lqo_oss_list) {
int j = 0;
for (i = 0, tgt = lov->tgts; i < ost_count; i++, tgt++) {
if (tgt->ltd_qos.ltq_oss == oss) {
/* Evenly space these OSTs across arrayspace */
int next = j * ost_count / oss->lqo_ost_count;
- while (lov->lov_qos.lq_rr_array[next] != LOV_QOS_EMPTY)
+ while (lov->lov_qos.lq_rr_array[next] !=
+ LOV_QOS_EMPTY)
next = (next + 1) % ost_count;
lov->lov_qos.lq_rr_array[next] = i;
j++;
+ placed++;
+ /* Protection against add races */
+ if (placed >= ost_count)
+ break;
}
}
LASSERT(j == oss->lqo_ost_count);
}
+ LASSERT(placed == ost_count);
lov->lov_qos.lq_dirty_rr = 0;
}
/* If we added a target we have to reconnect the llogs */
- /* Only do this at first add (idx), or the first time after recovery */
- if (idx != MDSLOV_NO_INDEX || 1/*FIXME*/) {
- CDEBUG(D_CONFIG, "reset llogs idx=%d\n", idx);
- /* Note that this will cause multiple mds/lov/osc_llog_init's
- with no llog_cleanup's, so fns should deal with that. */
- llog_cat_initialize(obd, mds->mds_lov_desc.ld_tgt_count);
- }
+ /* We only _need_ to do this at first add (idx), or the first time
+ after recovery. However, it should now be safe to call anytime. */
+ CDEBUG(D_CONFIG, "reset llogs idx=%d\n", idx);
+ llog_cat_initialize(obd, mds->mds_lov_desc.ld_tgt_count);
RETURN(rc);
}
LASSERT(cli->cl_mgc_vfsmnt == NULL);
+ /* Failsafes called at EOW */
config_log_end_all();
+ /* COMPAT_146 - old config logs may have added profiles we don't
+ know about */
+ class_del_profiles();
ptlrpcd_decref();
}
/* COMPAT_146 */
- /* For old logs, there was no start marker. */
/* FIXME only set this for old logs! */
- cld->cld_cfg.cfg_flags |= CFG_F_MARKER;
+ cld->cld_cfg.cfg_flags |= CFG_F_COMPAT146;
rc = mgc_process_log(obd, cld);
config_log_put(cld);
EXPORT_SYMBOL(class_decref);
EXPORT_SYMBOL(class_get_profile);
EXPORT_SYMBOL(class_del_profile);
+EXPORT_SYMBOL(class_del_profiles);
EXPORT_SYMBOL(class_process_config);
EXPORT_SYMBOL(class_config_parse_llog);
EXPORT_SYMBOL(class_config_dump_llog);
if (index < 0 || index >= LLOG_MAX_CTXTS)
RETURN(-EFAULT);
+
if (obd->obd_llog_ctxt[index]) {
/* mds_lov_update_mds might call here multiple times. So if the
llog is already set up then don't to do it again. */
{
struct lustre_profile *lprof;
int err = 0;
-
ENTRY;
+
+ CDEBUG(D_CONFIG, "Add profile %s\n", prof);
+
OBD_ALLOC(lprof, sizeof(*lprof));
if (lprof == NULL)
RETURN(-ENOMEM);
void class_del_profile(char *prof)
{
struct lustre_profile *lprof;
+ ENTRY;
+
+ CDEBUG(D_CONFIG, "Del profile %s\n", prof);
lprof = class_get_profile(prof);
if (lprof) {
OBD_FREE(lprof->lp_mdc, strlen(lprof->lp_mdc) + 1);
OBD_FREE(lprof, sizeof *lprof);
}
+ EXIT;
+}
+
+/* COMPAT_146 */
+void class_del_profiles(void)
+{
+ struct lustre_profile *lprof, *n;
+ ENTRY;
+
+ list_for_each_entry_safe(lprof, n, &lustre_profile_list, lp_list) {
+ list_del(&lprof->lp_list);
+ OBD_FREE(lprof->lp_profile, strlen(lprof->lp_profile) + 1);
+ OBD_FREE(lprof->lp_osc, strlen(lprof->lp_osc) + 1);
+ if (lprof->lp_mdc)
+ OBD_FREE(lprof->lp_mdc, strlen(lprof->lp_mdc) + 1);
+ OBD_FREE(lprof, sizeof *lprof);
+ }
+ EXIT;
}
int class_process_config(struct lustre_cfg *lcfg)
}
}
/* A config command without a start marker before it is
- illegal (1.4.6. compat must set it artificially) */
- if (!(clli->cfg_flags & CFG_F_MARKER) &&
+ illegal (post 146) */
+ if (!(clli->cfg_flags & CFG_F_COMPAT146) &&
+ !(clli->cfg_flags & CFG_F_MARKER) &&
(lcfg->lcfg_command != LCFG_MARKER)) {
CWARN("Config not inside markers, ignoring! (%#x)\n",
clli->cfg_flags);
clli->cfg_flags |= CFG_F_SKIP;
}
-
+
if (clli->cfg_flags & CFG_F_SKIP) {
- // FIXME warning
- CDEBUG(D_CONFIG|D_WARNING, "skipping %#x\n",
+ CDEBUG(D_CONFIG, "skipping %#x\n",
clli->cfg_flags);
rc = 0;
/* No processing! */
rc = obd_process_config(mgc, sizeof(*lcfg), lcfg);
lustre_cfg_free(lcfg);
+ if (rc == -EINVAL)
+ LCONSOLE_ERROR("%s: The configuration '%s' could not be read "
+ "from the MGS (%d). Make sure this client and "
+ "the MGS are running compatible versions of "
+ "Lustre.\n",
+ mgc->obd_name, logname, rc);
+
if (rc)
LCONSOLE_ERROR("%s: The configuration '%s' could not be read "
"from the MGS (%d). This may be the result of "
/**************** obd start *******************/
-static int do_lcfg(char *cfgname, lnet_nid_t nid, int cmd,
- char *s1, char *s2, char *s3, char *s4)
+int do_lcfg(char *cfgname, lnet_nid_t nid, int cmd,
+ char *s1, char *s2, char *s3, char *s4)
{
struct lustre_cfg_bufs bufs;
struct lustre_cfg * lcfg = NULL;
}
}
} else { /* client */
- /* use nids from mount line: uml1,1@elan:uml2,2@elan:/lustre */
+ /* Use nids from mount line: uml1,1@elan:uml2,2@elan:/lustre */
ptr = lsi->lsi_lmd->lmd_dev;
while (class_parse_nid(ptr, &nid, &ptr) == 0) {
rc = do_lcfg(LUSTRE_MGC_OBDNAME, nid,
LCFG_ADD_UUID, "mgsnid0", 0,0,0);
i++;
+ /* Stop at the first failover nid */
if (*ptr == ':')
break;
}
init_waitqueue_head(&waitq);
while ((atomic_read(&mnt->mnt_count) > 0) && retries--) {
- CWARN("Mount still busy with %d refs\n",
- atomic_read(&mnt->mnt_count));
+ LCONSOLE_WARN("Mount still busy with %d refs, waiting for "
+ "%d secs...\n",
+ atomic_read(&mnt->mnt_count), 2 * retries);
/* Wait for a bit */
lwi = LWI_TIMEOUT(2 * HZ, NULL, NULL);
EXPORT_SYMBOL(class_find_param);
EXPORT_SYMBOL(class_match_param);
EXPORT_SYMBOL(class_parse_nid);
+EXPORT_SYMBOL(do_lcfg);
goto out_close;
}
ret = 0;
- if (lsd.lsd_feature_compat & OBD_COMPAT_OST) {
+ vprint("Feature compat=%x, incompat=%x\n",
+ lsd.lsd_feature_compat, lsd.lsd_feature_incompat);
+
+ if ((lsd.lsd_feature_compat & OBD_COMPAT_OST) ||
+ (lsd.lsd_feature_incompat & OBD_INCOMPAT_OST)) {
mop->mo_ldd.ldd_flags = LDD_F_SV_TYPE_OST;
mop->mo_ldd.ldd_svindex = lsd.lsd_ost_index;
- } else if (lsd.lsd_feature_compat & OBD_COMPAT_MDT) {
+ } else if ((lsd.lsd_feature_compat & OBD_COMPAT_MDT) ||
+ (lsd.lsd_feature_incompat & OBD_INCOMPAT_MDT)) {
/* We must co-locate so mgs can see old logs.
If user doesn't want this, they can copy the old
logs manually and re-tunefs. */
/* The index won't be correct */
mop->mo_ldd.ldd_flags =
LDD_F_SV_TYPE_OST | LDD_F_NEED_INDEX;
+ vprint("OST with unknown index\n");
+
}
}
}
# prevent warnings on my uml
rm -f /lib/modules/`uname -r`/modules.*
echo "Depmod"
-depmod -a -e
+depmod -A -e
echo "Copying mount from local build dir to "$MDIR
cp -u ../utils/mount.lustre /sbin/.