* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
- * Copyright (c) 2011, 2016, Intel Corporation.
+ * Copyright (c) 2011, 2017, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
#define D_MGS D_CONFIG
#include <obd.h>
-#include <lustre_ioctl.h>
-#include <lustre_param.h>
+#include <uapi/linux/lustre/lustre_ioctl.h>
+#include <uapi/linux/lustre/lustre_param.h>
#include <lustre_sec.h>
#include <lustre_quota.h>
+#include <lustre_sec.h>
#include "mgs_internal.h"
GOTO(out_free, rc = -E2BIG);
/* Modify mostly means cancel */
mml->mml_marker.cm_flags = flags;
- mml->mml_marker.cm_canceltime = flags ? cfs_time_current_sec() : 0;
+ mml->mml_marker.cm_canceltime = flags ? ktime_get_real_seconds() : 0;
mml->mml_modified = 0;
rc = llog_process(env, loghandle, mgs_modify_handler, (void *)mml,
NULL);
}
/** This structure is passed to mgs_replace_handler */
-struct mgs_replace_uuid_lookup {
+struct mgs_replace_data {
/* Nids are replaced for this target device */
struct mgs_target_info target;
/* Temporary modified llog */
* b) is it target block
*
* \param[in] lcfg
- * \param[in] mrul
+ * \param[in] mrd
*
* \retval 0 should not to be skipped
* \retval 1 should to be skipped
*/
static int check_markers(struct lustre_cfg *lcfg,
- struct mgs_replace_uuid_lookup *mrul)
+ struct mgs_replace_data *mrd)
{
struct cfg_marker *marker;
and can be restored if needed */
if ((marker->cm_flags & (CM_EXCLUDE | CM_START)) ==
(CM_EXCLUDE | CM_START)) {
- mrul->skip_it = 1;
+ mrd->skip_it = 1;
return 1;
}
if ((marker->cm_flags & (CM_EXCLUDE | CM_END)) ==
(CM_EXCLUDE | CM_END)) {
- mrul->skip_it = 0;
+ mrd->skip_it = 0;
return 1;
}
- if (strcmp(mrul->target.mti_svname, marker->cm_tgtname) == 0) {
+ if (strcmp(mrd->target.mti_svname, marker->cm_tgtname) == 0) {
LASSERT(!(marker->cm_flags & CM_START) ||
!(marker->cm_flags & CM_END));
if (marker->cm_flags & CM_START) {
- mrul->in_target_device = 1;
- mrul->device_nids_added = 0;
+ mrd->in_target_device = 1;
+ mrd->device_nids_added = 0;
} else if (marker->cm_flags & CM_END)
- mrul->in_target_device = 0;
+ mrd->in_target_device = 0;
}
}
* \retval 0 record is not processed.
*/
static int process_command(const struct lu_env *env, struct lustre_cfg *lcfg,
- struct mgs_replace_uuid_lookup *mrul)
+ struct mgs_replace_data *mrd)
{
int nids_added = 0;
lnet_nid_t nid;
if (lcfg->lcfg_command == LCFG_ADD_UUID) {
/* LCFG_ADD_UUID command found. Let's skip original command
and add passed nids */
- ptr = mrul->target.mti_params;
+ ptr = mrd->target.mti_params;
while (class_parse_nid(ptr, &nid, &ptr) == 0) {
CDEBUG(D_MGS, "add nid %s with uuid %s, "
"device %s\n", libcfs_nid2str(nid),
- mrul->target.mti_params,
- mrul->target.mti_svname);
+ mrd->target.mti_params,
+ mrd->target.mti_svname);
rc = record_add_uuid(env,
- mrul->temp_llh, nid,
- mrul->target.mti_params);
+ mrd->temp_llh, nid,
+ mrd->target.mti_params);
if (!rc)
nids_added++;
}
if (nids_added == 0) {
CERROR("No new nids were added, nid %s with uuid %s, "
"device %s\n", libcfs_nid2str(nid),
- mrul->target.mti_params,
- mrul->target.mti_svname);
+ mrd->target.mti_params,
+ mrd->target.mti_svname);
RETURN(-ENXIO);
} else {
- mrul->device_nids_added = 1;
+ mrd->device_nids_added = 1;
}
return nids_added;
}
- if (mrul->device_nids_added && lcfg->lcfg_command == LCFG_SETUP) {
+ if (mrd->device_nids_added && lcfg->lcfg_command == LCFG_SETUP) {
/* LCFG_SETUP command found. UUID should be changed */
rc = record_setup(env,
- mrul->temp_llh,
+ mrd->temp_llh,
/* devname the same */
lustre_cfg_string(lcfg, 0),
/* s1 is not changed */
lustre_cfg_string(lcfg, 1),
/* new uuid should be
the full nidlist */
- mrul->target.mti_params,
+ mrd->target.mti_params,
/* s3 is not changed */
lustre_cfg_string(lcfg, 3),
/* s4 is not changed */
*
* \param[in] llh log to be processed
* \param[in] rec current record
- * \param[in] data mgs_replace_uuid_lookup structure
+ * \param[in] data mgs_replace_data structure
*
* \retval 0 success
*/
-static int mgs_replace_handler(const struct lu_env *env,
- struct llog_handle *llh,
- struct llog_rec_hdr *rec,
- void *data)
+static int mgs_replace_nids_handler(const struct lu_env *env,
+ struct llog_handle *llh,
+ struct llog_rec_hdr *rec,
+ void *data)
{
- struct mgs_replace_uuid_lookup *mrul;
+ struct mgs_replace_data *mrd;
struct lustre_cfg *lcfg = REC_DATA(rec);
int cfg_len = REC_DATA_LEN(rec);
int rc;
ENTRY;
- mrul = (struct mgs_replace_uuid_lookup *)data;
+ mrd = (struct mgs_replace_data *)data;
if (rec->lrh_type != OBD_CFG_REC) {
CERROR("unhandled lrh_type: %#x, cmd %x %s %s\n",
GOTO(skip_out, rc = 0);
}
- rc = check_markers(lcfg, mrul);
- if (rc || mrul->skip_it)
+ rc = check_markers(lcfg, mrd);
+ if (rc || mrd->skip_it)
GOTO(skip_out, rc = 0);
/* Write to new log all commands outside target device block */
- if (!mrul->in_target_device)
+ if (!mrd->in_target_device)
GOTO(copy_out, rc = 0);
/* Skip all other LCFG_ADD_UUID and LCFG_ADD_CONN records
(failover nids) for this target, assuming that if then
primary is changing then so is the failover */
- if (mrul->device_nids_added &&
+ if (mrd->device_nids_added &&
(lcfg->lcfg_command == LCFG_ADD_UUID ||
lcfg->lcfg_command == LCFG_ADD_CONN))
GOTO(skip_out, rc = 0);
- rc = process_command(env, lcfg, mrul);
+ rc = process_command(env, lcfg, mrd);
if (rc < 0)
RETURN(rc);
RETURN(0);
copy_out:
/* Record is placed in temporary llog as is */
- rc = llog_write(env, mrul->temp_llh, rec, LLOG_NEXT_IDX);
+ rc = llog_write(env, mrd->temp_llh, rec, LLOG_NEXT_IDX);
CDEBUG(D_MGS, "Copied idx=%d, rc=%d, len=%d, cmd %x %s %s\n",
rec->lrh_index, rc, rec->lrh_len, lcfg->lcfg_command,
return rc;
}
-static int mgs_replace_nids_log(const struct lu_env *env,
- struct obd_device *mgs, struct fs_db *fsdb,
- char *logname, char *devname, char *nids)
+static int mgs_replace_log(const struct lu_env *env,
+ struct obd_device *mgs,
+ char *logname, char *devname,
+ llog_cb_t replace_handler, void *data)
{
struct llog_handle *orig_llh, *backup_llh;
struct llog_ctxt *ctxt;
- struct mgs_replace_uuid_lookup *mrul;
+ struct mgs_replace_data *mrd;
struct mgs_device *mgs_dev = lu2mgs_dev(mgs->obd_lu_dev);
static struct obd_uuid cfg_uuid = { .uuid = "config_uuid" };
char *backup;
- int rc, rc2;
+ int rc, rc2, buf_size;
+ time64_t now;
ENTRY;
- CDEBUG(D_MGS, "Replace nids for %s in %s\n", devname, logname);
-
ctxt = llog_get_context(mgs, LLOG_CONFIG_ORIG_CTXT);
LASSERT(ctxt != NULL);
GOTO(out_put, rc = 0);
}
- OBD_ALLOC(backup, strlen(logname) + strlen(".bak") + 1);
+ now = ktime_get_real_seconds();
+
+ /* max time64_t in decimal fits into 20 bytes long string */
+ buf_size = strlen(logname) + 1 + 20 + 1 + strlen(".bak") + 1;
+ OBD_ALLOC(backup, buf_size);
if (backup == NULL)
GOTO(out_put, rc = -ENOMEM);
- sprintf(backup, "%s.bak", logname);
+ snprintf(backup, buf_size, "%s.%llu.bak", logname, now);
rc = llog_backup(env, mgs, ctxt, ctxt, logname, backup);
if (rc == 0) {
if (llog_get_size(backup_llh) <= 1)
GOTO(out_close, rc = 0);
- OBD_ALLOC_PTR(mrul);
- if (!mrul)
+ OBD_ALLOC_PTR(mrd);
+ if (!mrd)
GOTO(out_close, rc = -ENOMEM);
/* devname is only needed information to replace UUID records */
- strlcpy(mrul->target.mti_svname, devname,
- sizeof(mrul->target.mti_svname));
- /* parse nids later */
- strlcpy(mrul->target.mti_params, nids, sizeof(mrul->target.mti_params));
+ if (devname)
+ strlcpy(mrd->target.mti_svname, devname,
+ sizeof(mrd->target.mti_svname));
+ /* data is parsed in llog callback */
+ if (data)
+ strlcpy(mrd->target.mti_params, data,
+ sizeof(mrd->target.mti_params));
/* Copy records to this temporary llog */
- mrul->temp_llh = orig_llh;
+ mrd->temp_llh = orig_llh;
- rc = llog_process(env, backup_llh, mgs_replace_handler,
- (void *)mrul, NULL);
- OBD_FREE_PTR(mrul);
+ rc = llog_process(env, backup_llh, replace_handler,
+ (void *)mrd, NULL);
+ OBD_FREE_PTR(mrd);
out_close:
rc2 = llog_close(NULL, backup_llh);
if (!rc)
}
out_free:
- OBD_FREE(backup, strlen(backup) + 1);
+ OBD_FREE(backup, buf_size);
out_put:
llog_ctxt_put(ctxt);
if (rc)
- CERROR("%s: failed to replace nids in log %s: rc = %d\n",
+ CERROR("%s: failed to replace log %s: rc = %d\n",
mgs->obd_name, logname, rc);
RETURN(rc);
}
+static int mgs_replace_nids_log(const struct lu_env *env,
+ struct obd_device *obd,
+ char *logname, char *devname, char *nids)
+{
+ CDEBUG(D_MGS, "Replace NIDs for %s in %s\n", devname, logname);
+ return mgs_replace_log(env, obd, logname, devname,
+ mgs_replace_nids_handler, nids);
+}
+
/**
* Parse device name and get file system name and/or device index
*
- * \param[in] devname device name (ex. lustre-MDT0000)
- * \param[out] fsname file system name(optional)
- * \param[out] index device index(optional)
+ * @devname device name (ex. lustre-MDT0000)
+ * @fsname file system name extracted from @devname and returned
+ * to the caller (optional)
+ * @index device index extracted from @devname and returned to
+ * the caller (optional)
*
- * \retval 0 success
+ * RETURN 0 success if we are only interested in
+ * extracting fsname from devname.
+ * i.e index is NULL
+ *
+ * LDD_F_SV_TYPE_* Besides extracting the fsname the
+ * user also wants the index. Report to
+ * the user the type of obd device the
+ * returned index belongs too.
+ *
+ * -EINVAL The obd device name is improper so
+ * fsname could not be extracted.
+ *
+ * -ENXIO Failed to extract the index out of
+ * the obd device name. Most likely an
+ * invalid obd device name
*/
-static int mgs_parse_devname(char *devname, char *fsname, __u32 *index)
+static int mgs_parse_devname(char *devname, char *fsname, u32 *index)
{
- int rc;
+ int rc = 0;
ENTRY;
/* Extract fsname */
if (rc < 0) {
CDEBUG(D_MGS, "Device name %s with wrong index\n",
devname);
- RETURN(-EINVAL);
+ RETURN(-ENXIO);
}
}
- RETURN(0);
+ /* server_name2index can return LDD_F_SV_TYPE_* so always return rc */
+ RETURN(rc);
}
/* This is only called during replace_nids */
GOTO(out, rc = -EINPROGRESS);
}
- /* Get fsname and index*/
+ /* Get fsname and index */
rc = mgs_parse_devname(devname, fsname, &index);
- if (rc)
+ if (rc < 0)
GOTO(out, rc);
rc = mgs_find_or_make_fsdb(env, mgs, fsname, &fsdb);
/* Process client llogs */
name_create(&logname, fsname, "-client");
- rc = mgs_replace_nids_log(env, mgs_obd, fsdb, logname, devname, nids);
+ rc = mgs_replace_nids_log(env, mgs_obd, logname, devname, nids);
name_destroy(&logname);
if (rc) {
CERROR("%s: error while replacing NIDs for %s: rc = %d\n",
if (!test_bit(i, fsdb->fsdb_mdt_index_map))
continue;
name_create_mdt(&logname, fsname, i);
- rc = mgs_replace_nids_log(env, mgs_obd, fsdb, logname, devname, nids);
+ rc = mgs_replace_nids_log(env, mgs_obd, logname, devname, nids);
name_destroy(&logname);
if (rc)
GOTO(out, rc);
RETURN(rc);
}
+/**
+ * This is called for every record in llog. Some of records are
+ * skipped, others are copied to new log as is.
+ * Records to be skipped are
+ * marker records marked SKIP
+ * records enclosed between SKIP markers
+ *
+ * \param[in] llh log to be processed
+ * \param[in] rec current record
+ * \param[in] data mgs_replace_data structure
+ *
+ * \retval 0 success
+ **/
+static int mgs_clear_config_handler(const struct lu_env *env,
+ struct llog_handle *llh,
+ struct llog_rec_hdr *rec, void *data)
+{
+ struct mgs_replace_data *mrd;
+ struct lustre_cfg *lcfg = REC_DATA(rec);
+ int cfg_len = REC_DATA_LEN(rec);
+ int rc;
+
+ ENTRY;
+
+ mrd = (struct mgs_replace_data *)data;
+
+ if (rec->lrh_type != OBD_CFG_REC) {
+ CDEBUG(D_MGS, "Config llog Name=%s, Record Index=%u, "
+ "Unhandled Record Type=%#x\n", llh->lgh_name,
+ rec->lrh_index, rec->lrh_type);
+ RETURN(-EINVAL);
+ }
+
+ rc = lustre_cfg_sanity_check(lcfg, cfg_len);
+ if (rc) {
+ CDEBUG(D_MGS, "Config llog Name=%s, Invalid config file.",
+ llh->lgh_name);
+ RETURN(-EINVAL);
+ }
+
+ if (lcfg->lcfg_command == LCFG_MARKER) {
+ struct cfg_marker *marker;
+
+ marker = lustre_cfg_buf(lcfg, 1);
+ if (marker->cm_flags & CM_SKIP) {
+ if (marker->cm_flags & CM_START)
+ mrd->skip_it = 1;
+ if (marker->cm_flags & CM_END)
+ mrd->skip_it = 0;
+ /* SKIP section started or finished */
+ CDEBUG(D_MGS, "Skip idx=%d, rc=%d, len=%d, "
+ "cmd %x %s %s\n", rec->lrh_index, rc,
+ rec->lrh_len, lcfg->lcfg_command,
+ lustre_cfg_string(lcfg, 0),
+ lustre_cfg_string(lcfg, 1));
+ RETURN(0);
+ }
+ } else {
+ if (mrd->skip_it) {
+ /* record enclosed between SKIP markers, skip it */
+ CDEBUG(D_MGS, "Skip idx=%d, rc=%d, len=%d, "
+ "cmd %x %s %s\n", rec->lrh_index, rc,
+ rec->lrh_len, lcfg->lcfg_command,
+ lustre_cfg_string(lcfg, 0),
+ lustre_cfg_string(lcfg, 1));
+ RETURN(0);
+ }
+ }
+
+ /* Record is placed in temporary llog as is */
+ rc = llog_write(env, mrd->temp_llh, rec, LLOG_NEXT_IDX);
+
+ CDEBUG(D_MGS, "Copied idx=%d, rc=%d, len=%d, cmd %x %s %s\n",
+ rec->lrh_index, rc, rec->lrh_len, lcfg->lcfg_command,
+ lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1));
+ RETURN(rc);
+}
+
+/*
+ * Directory CONFIGS/ may contain files which are not config logs to
+ * be cleared. Skip any llogs with a non-alphanumeric character after
+ * the last '-'. For example, fsname-MDT0000.sav, fsname-MDT0000.bak,
+ * fsname-MDT0000.orig, fsname-MDT0000~, fsname-MDT0000.20150516, etc.
+ */
+static bool config_to_clear(const char *logname)
+{
+ int i;
+ char *str;
+
+ str = strrchr(logname, '-');
+ if (!str)
+ return 0;
+
+ i = 0;
+ while (isalnum(str[++i]));
+ return str[i] == '\0';
+}
+
+/**
+ * Clear config logs for \a name
+ *
+ * \param env
+ * \param mgs MGS device
+ * \param name name of device or of filesystem
+ * (ex. lustre-OST0000 or lustre) in later case all logs
+ * will be cleared
+ *
+ * \retval 0 success
+ */
+int mgs_clear_configs(const struct lu_env *env,
+ struct mgs_device *mgs, const char *name)
+{
+ struct list_head dentry_list;
+ struct mgs_direntry *dirent, *n;
+ char *namedash;
+ int conn_state;
+ struct obd_device *mgs_obd = mgs->mgs_obd;
+ int rc;
+
+ ENTRY;
+
+ /* Prevent clients and servers from connecting to mgs */
+ spin_lock(&mgs_obd->obd_dev_lock);
+ conn_state = mgs_obd->obd_no_conn;
+ mgs_obd->obd_no_conn = 1;
+ spin_unlock(&mgs_obd->obd_dev_lock);
+
+ /*
+ * config logs cannot be cleaned if anything other than
+ * MGS is started
+ */
+ if (!only_mgs_is_running(mgs_obd)) {
+ CERROR("Only MGS is allowed to be started\n");
+ GOTO(out, rc = -EBUSY);
+ }
+
+ /* Find all the logs in the CONFIGS directory */
+ rc = class_dentry_readdir(env, mgs, &dentry_list);
+ if (rc) {
+ CERROR("%s: cannot read config directory '%s': rc = %d\n",
+ mgs_obd->obd_name, MOUNT_CONFIGS_DIR, rc);
+ GOTO(out, rc);
+ }
+
+ if (list_empty(&dentry_list)) {
+ CERROR("%s: list empty reading config dir '%s': rc = %d\n",
+ mgs_obd->obd_name, MOUNT_CONFIGS_DIR, -ENOENT);
+ GOTO(out, rc = -ENOENT);
+ }
+
+ OBD_ALLOC(namedash, strlen(name) + 2);
+ if (namedash == NULL)
+ GOTO(out, rc = -ENOMEM);
+ snprintf(namedash, strlen(name) + 2, "%s-", name);
+
+ list_for_each_entry(dirent, &dentry_list, mde_list) {
+ if (strcmp(name, dirent->mde_name) &&
+ strncmp(namedash, dirent->mde_name, strlen(namedash)))
+ continue;
+ if (!config_to_clear(dirent->mde_name))
+ continue;
+ CDEBUG(D_MGS, "%s: Clear config log %s\n",
+ mgs_obd->obd_name, dirent->mde_name);
+ rc = mgs_replace_log(env, mgs_obd, dirent->mde_name, NULL,
+ mgs_clear_config_handler, NULL);
+ if (rc)
+ break;
+ }
+
+ list_for_each_entry_safe(dirent, n, &dentry_list, mde_list) {
+ list_del_init(&dirent->mde_list);
+ mgs_direntry_free(dirent);
+ }
+ OBD_FREE(namedash, strlen(name) + 2);
+out:
+ spin_lock(&mgs_obd->obd_dev_lock);
+ mgs_obd->obd_no_conn = conn_state;
+ spin_unlock(&mgs_obd->obd_dev_lock);
+
+ RETURN(rc);
+}
+
static int record_lov_setup(const struct lu_env *env, struct llog_handle *llh,
char *devname, struct lov_desc *desc)
{
sizeof(mgi->mgi_marker.cm_comment));
if (cplen >= sizeof(mgi->mgi_marker.cm_comment))
return -E2BIG;
- mgi->mgi_marker.cm_createtime = cfs_time_current_sec();
+ mgi->mgi_marker.cm_createtime = ktime_get_real_seconds();
mgi->mgi_marker.cm_canceltime = 0;
lustre_cfg_bufs_reset(&mgi->mgi_bufs, NULL);
lustre_cfg_bufs_set(&mgi->mgi_bufs, 1, &mgi->mgi_marker,
if (lcfg->lcfg_command == LCFG_SPTLRPC_CONF)
RETURN(rc);
- if (lcfg->lcfg_command == LCFG_ADD_MDC) {
+ if (lcfg->lcfg_command == LCFG_ADD_MDC &&
+ strstr(lustre_cfg_string(lcfg, 0), "-clilmv") != NULL) {
int index;
if (sscanf(lustre_cfg_buf(lcfg, 2), "%d", &index) != 1)
if (rc)
GOTO(out_free, rc);
- rc = record_marker(env, llh, fsdb, CM_START, cliname,
- "mount opts");
+ rc = record_marker(env, llh, fsdb, CM_START, cliname, "mount opts");
if (rc)
GOTO(out_end, rc);
rc = record_mount_opt(env, llh, cliname, fsdb->fsdb_clilov,
fsdb->fsdb_clilmv);
if (rc)
GOTO(out_end, rc);
- rc = record_marker(env, llh, fsdb, CM_END, cliname,
- "mount opts");
-
+ rc = record_marker(env, llh, fsdb, CM_END, cliname, "mount opts");
if (rc)
GOTO(out_end, rc);
/* Add ost to all MDT lov defs */
for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
if (test_bit(i, fsdb->fsdb_mdt_index_map)) {
- char mdt_index[9];
+ char mdt_index[13];
rc = name_create_mdt_and_lov(&logname, &lovname, fsdb,
i);
if (rc)
RETURN(rc);
- sprintf(mdt_index, "-MDT%04x", i);
+
+ snprintf(mdt_index, sizeof(mdt_index), "-MDT%04x", i);
rc = mgs_write_log_osc_to_lov(env, mgs, fsdb, mti,
logname, mdt_index,
lovname, LUSTRE_SP_MDT,
/* FIXME we currently can't erase the failnids
* given when a target first registers, since they aren't part of
- * an "add uuid" stanza */
+ * an "add uuid" stanza
+ */
/* Verify that we know about this target */
if (mgs_log_is_empty(env, mgs, mti->mti_svname)) {
}
if (rc)
RETURN(rc);
+
/* Add failover nids to the client log */
rc = name_create(&logname, mti->mti_fsname, "-client");
if (rc) {
name_destroy(&cliname);
RETURN(rc);
}
+
rc = mgs_write_log_failnid_internal(env, mgs, fsdb,mti,logname,cliname);
name_destroy(&logname);
name_destroy(&cliname);
return rc;
}
-static int mgs_write_log_param2(const struct lu_env *env,
- struct mgs_device *mgs,
- struct fs_db *fsdb,
- struct mgs_target_info *mti, char *ptr)
-{
- struct lustre_cfg_bufs bufs;
- int rc = 0;
- ENTRY;
-
- CDEBUG(D_MGS, "next param '%s'\n", ptr);
- rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, PARAMS_FILENAME, &bufs,
- mti->mti_svname, ptr);
-
- RETURN(rc);
-}
-
/* write global variable settings into log */
static int mgs_write_log_sys(const struct lu_env *env,
struct mgs_device *mgs, struct fs_db *fsdb,
CDEBUG(D_MGS, "global '%s'\n", quota);
if (strchr(tmp, 'u') == NULL && strchr(tmp, 'g') == NULL &&
+ strchr(tmp, 'p') == NULL &&
strcmp(tmp, "none") != 0) {
CERROR("enable option(%s) isn't supported\n", tmp);
return -EINVAL;
RETURN(rc);
}
+static int mgs_write_log_param2(const struct lu_env *env,
+ struct mgs_device *mgs,
+ struct fs_db *fsdb,
+ struct mgs_target_info *mti, char *ptr)
+{
+ struct lustre_cfg_bufs bufs;
+ int rc;
+
+ ENTRY;
+ CDEBUG(D_MGS, "next param '%s'\n", ptr);
+
+ /* PARAM_MGSNODE and PARAM_NETWORK are set only when formating
+ * or during the inital mount. It can never change after that.
+ */
+ if (!class_match_param(ptr, PARAM_MGSNODE, NULL) ||
+ !class_match_param(ptr, PARAM_NETWORK, NULL)) {
+ rc = 0;
+ goto end;
+ }
+
+ /* Processed in mgs_write_log_ost. Another value that can't
+ * be changed by lctl set_param -P.
+ */
+ if (!class_match_param(ptr, PARAM_FAILMODE, NULL)) {
+ LCONSOLE_ERROR_MSG(0x169,
+ "%s can only be changed with tunefs.lustre and --writeconf\n",
+ ptr);
+ rc = -EPERM;
+ goto end;
+ }
+
+ /* FIXME !!! Support for sptlrpc is incomplete. Currently the change
+ * doesn't transmit to the client. See LU-7183.
+ */
+ if (!class_match_param(ptr, PARAM_SRPC, NULL)) {
+ rc = mgs_srpc_set_param(env, mgs, fsdb, mti, ptr);
+ goto end;
+ }
+
+ /* Can't use class_match_param since ptr doesn't start with
+ * PARAM_FAILNODE. So we look for PARAM_FAILNODE contained in ptr.
+ */
+ if (strstr(ptr, PARAM_FAILNODE)) {
+ /* Add a failover nidlist. We already processed failovers
+ * params for new targets in mgs_write_log_target.
+ */
+ const char *param;
+
+ /* can't use wildcards with failover.node */
+ if (strchr(ptr, '*')) {
+ rc = -ENODEV;
+ goto end;
+ }
+
+ param = strstr(ptr, PARAM_FAILNODE);
+ if (strlcpy(mti->mti_params, param, sizeof(mti->mti_params)) >=
+ sizeof(mti->mti_params)) {
+ rc = -E2BIG;
+ goto end;
+ }
+
+ CDEBUG(D_MGS, "Adding failnode with param %s\n",
+ mti->mti_params);
+ rc = mgs_write_log_add_failnid(env, mgs, fsdb, mti);
+ goto end;
+ }
+
+ rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, PARAMS_FILENAME, &bufs,
+ mti->mti_svname, ptr);
+end:
+ RETURN(rc);
+}
+
/* Permanent settings of all parameters by writing into the appropriate
* configuration logs.
* A parameter with null value ("<param>='\0'") means to erase it out of
LCONSOLE_ERROR_MSG(0x144, "%s: MDC0 can not be"
" (de)activated.\n",
mti->mti_svname);
- GOTO(end, rc = -EINVAL);
+ GOTO(end, rc = -EPERM);
}
}
/* All mdd., ost. and osd. params in proc */
if ((class_match_param(ptr, PARAM_MDD, NULL) == 0) ||
+ (class_match_param(ptr, PARAM_LOD, NULL) == 0) ||
(class_match_param(ptr, PARAM_OST, NULL) == 0) ||
(class_match_param(ptr, PARAM_OSD, NULL) == 0)) {
CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
RETURN(rc);
}
-/* from llog_swab */
-static void print_lustre_cfg(struct lustre_cfg *lcfg)
-{
- int i;
- ENTRY;
-
- CDEBUG(D_MGS, "lustre_cfg: %p\n", lcfg);
- CDEBUG(D_MGS, "\tlcfg->lcfg_version: %#x\n", lcfg->lcfg_version);
-
- CDEBUG(D_MGS, "\tlcfg->lcfg_command: %#x\n", lcfg->lcfg_command);
- CDEBUG(D_MGS, "\tlcfg->lcfg_num: %#x\n", lcfg->lcfg_num);
- CDEBUG(D_MGS, "\tlcfg->lcfg_flags: %#x\n", lcfg->lcfg_flags);
- CDEBUG(D_MGS, "\tlcfg->lcfg_nid: %s\n", libcfs_nid2str(lcfg->lcfg_nid));
-
- CDEBUG(D_MGS, "\tlcfg->lcfg_bufcount: %d\n", lcfg->lcfg_bufcount);
- if (lcfg->lcfg_bufcount < LUSTRE_CFG_MAX_BUFCOUNT)
- for (i = 0; i < lcfg->lcfg_bufcount; i++) {
- CDEBUG(D_MGS, "\tlcfg->lcfg_buflens[%d]: %d %s\n",
- i, lcfg->lcfg_buflens[i],
- lustre_cfg_string(lcfg, i));
- }
- EXIT;
-}
-
/* Setup _mgs fsdb and log
*/
int mgs__mgs_fsdb_setup(const struct lu_env *env, struct mgs_device *mgs)
return rc == -ENOENT ? 0 : rc;
}
-/* Set a permanent (config log) param for a target or fs
- * \param lcfg buf0 may contain the device (testfs-MDT0000) name
- * buf1 contains the single parameter
- */
-int mgs_setparam(const struct lu_env *env, struct mgs_device *mgs,
- struct lustre_cfg *lcfg, char *fsname)
+/**
+ * Fill in the mgs_target_info based on data devname and param provide.
+ *
+ * @env thread context
+ * @mgs mgs device
+ * @mti mgs target info. We want to set this based other paramters
+ * passed to this function. Once setup we write it to the config
+ * logs.
+ * @devname optional OBD device name
+ * @param string that contains both what tunable to set and the value to
+ * set it to.
+ *
+ * RETURN 0 for success
+ * negative error number on failure
+ **/
+static int mgs_set_conf_param(const struct lu_env *env, struct mgs_device *mgs,
+ struct mgs_target_info *mti, const char *devname,
+ const char *param)
{
struct fs_db *fsdb = NULL;
- struct mgs_target_info *mti = NULL;
- char *devname, *param;
- char *ptr;
- const char *tmp;
- __u32 index;
+ int dev_type;
int rc = 0;
- bool free = false;
+
ENTRY;
+ /* lustre, lustre-mdtlov, lustre-client, lustre-MDT0000 */
+ if (!devname) {
+ size_t len;
+
+ /* We have two possible cases here:
+ *
+ * 1) the device name embedded in the param:
+ * lustre-OST0000.osc.max_dirty_mb=32
+ *
+ * 2) the file system name is embedded in
+ * the param: lustre.sys.at.min=0
+ */
+ len = strcspn(param, ".=");
+ if (!len || param[len] == '=')
+ RETURN(-EINVAL);
- print_lustre_cfg(lcfg);
+ if (len >= sizeof(mti->mti_svname))
+ RETURN(-E2BIG);
- /* lustre, lustre-mdtlov, lustre-client, lustre-MDT0000 */
- devname = lustre_cfg_string(lcfg, 0);
- param = lustre_cfg_string(lcfg, 1);
- if (!devname) {
- /* Assume device name embedded in param:
- lustre-OST0000.osc.max_dirty_mb=32 */
- ptr = strchr(param, '.');
- if (ptr) {
- devname = param;
- *ptr = 0;
- param = ptr + 1;
- }
- }
- if (!devname) {
- LCONSOLE_ERROR_MSG(0x14d, "No target specified: %s\n", param);
- RETURN(-ENOSYS);
- }
+ snprintf(mti->mti_svname, sizeof(mti->mti_svname),
+ "%.*s", (int)len, param);
+ param += len + 1;
+ } else {
+ if (strlcpy(mti->mti_svname, devname, sizeof(mti->mti_svname)) >=
+ sizeof(mti->mti_svname))
+ RETURN(-E2BIG);
+ }
- rc = mgs_parse_devname(devname, fsname, NULL);
- if (rc == 0 && !mgs_parse_devname(devname, NULL, &index)) {
- /* param related to llite isn't allowed to set by OST or MDT */
- if (rc == 0 && strncmp(param, PARAM_LLITE,
- sizeof(PARAM_LLITE) - 1) == 0)
- RETURN(-EINVAL);
- } else {
- /* assume devname is the fsname */
- strlcpy(fsname, devname, MTI_NAME_MAXLEN);
- }
- CDEBUG(D_MGS, "setparam fs='%s' device='%s'\n", fsname, devname);
+ if (!strlen(mti->mti_svname)) {
+ LCONSOLE_ERROR_MSG(0x14d, "No target specified: %s\n", param);
+ RETURN(-ENOSYS);
+ }
- rc = mgs_find_or_make_fsdb(env, mgs,
- lcfg->lcfg_command == LCFG_SET_PARAM ?
- PARAMS_FILENAME : fsname, &fsdb);
+ dev_type = mgs_parse_devname(mti->mti_svname, mti->mti_fsname,
+ &mti->mti_stripe_index);
+ switch (dev_type) {
+ /* For this case we have an invalid obd device name */
+ case -ENXIO:
+ CDEBUG(D_MGS, "%s don't contain an index\n", mti->mti_svname);
+ strlcpy(mti->mti_fsname, mti->mti_svname, MTI_NAME_MAXLEN);
+ dev_type = 0;
+ break;
+ /* Not an obd device, assume devname is the fsname.
+ * User might of only provided fsname and not obd device
+ */
+ case -EINVAL:
+ CDEBUG(D_MGS, "%s is seen as a file system name\n", mti->mti_svname);
+ strlcpy(mti->mti_fsname, mti->mti_svname, MTI_NAME_MAXLEN);
+ dev_type = 0;
+ break;
+ default:
+ if (dev_type < 0)
+ GOTO(out, rc = dev_type);
+
+ /* param related to llite isn't allowed to set by OST or MDT */
+ if (dev_type & LDD_F_SV_TYPE_OST ||
+ dev_type & LDD_F_SV_TYPE_MDT) {
+ /* param related to llite isn't allowed to set by OST
+ * or MDT
+ */
+ if (!strncmp(param, PARAM_LLITE,
+ sizeof(PARAM_LLITE) - 1))
+ GOTO(out, rc = -EINVAL);
+
+ /* Strip -osc or -mdc suffix from svname */
+ if (server_make_name(dev_type, mti->mti_stripe_index,
+ mti->mti_fsname, mti->mti_svname,
+ sizeof(mti->mti_svname)))
+ GOTO(out, rc = -EINVAL);
+ }
+ break;
+ }
+
+ if (strlcpy(mti->mti_params, param, sizeof(mti->mti_params)) >=
+ sizeof(mti->mti_params))
+ GOTO(out, rc = -E2BIG);
+
+ CDEBUG(D_MGS, "set_conf_param fs='%s' device='%s' param='%s'\n",
+ mti->mti_fsname, mti->mti_svname, mti->mti_params);
+
+ rc = mgs_find_or_make_fsdb(env, mgs, mti->mti_fsname, &fsdb);
if (rc)
- RETURN(rc);
+ GOTO(out, rc);
- if (lcfg->lcfg_command != LCFG_SET_PARAM &&
- !test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags) &&
+ if (!test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags) &&
test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags)) {
CERROR("No filesystem targets for %s. cfg_device from lctl "
- "is '%s'\n", fsname, devname);
- free = true;
+ "is '%s'\n", mti->mti_fsname, mti->mti_svname);
+ mgs_unlink_fsdb(mgs, fsdb);
GOTO(out, rc = -EINVAL);
}
- /* Create a fake mti to hold everything */
- OBD_ALLOC_PTR(mti);
- if (!mti)
- GOTO(out, rc = -ENOMEM);
- if (strlcpy(mti->mti_fsname, fsname, sizeof(mti->mti_fsname))
- >= sizeof(mti->mti_fsname))
- GOTO(out, rc = -E2BIG);
- if (strlcpy(mti->mti_svname, devname, sizeof(mti->mti_svname))
- >= sizeof(mti->mti_svname))
- GOTO(out, rc = -E2BIG);
- if (strlcpy(mti->mti_params, param, sizeof(mti->mti_params))
- >= sizeof(mti->mti_params))
- GOTO(out, rc = -E2BIG);
- rc = server_name2index(mti->mti_svname, &mti->mti_stripe_index, &tmp);
- if (rc < 0)
- /* Not a valid server; may be only fsname */
- rc = 0;
- else
- /* Strip -osc or -mdc suffix from svname */
- if (server_make_name(rc, mti->mti_stripe_index, mti->mti_fsname,
- mti->mti_svname, sizeof(mti->mti_svname)))
- GOTO(out, rc = -EINVAL);
/*
* Revoke lock so everyone updates. Should be alright if
* someone was already reading while we were updating the logs,
* so we don't really need to hold the lock while we're
* writing (above).
*/
- if (lcfg->lcfg_command == LCFG_SET_PARAM) {
- mti->mti_flags = rc | LDD_F_PARAM2;
- mutex_lock(&fsdb->fsdb_mutex);
- rc = mgs_write_log_param2(env, mgs, fsdb, mti, mti->mti_params);
- mutex_unlock(&fsdb->fsdb_mutex);
- mgs_revoke_lock(mgs, fsdb, CONFIG_T_PARAMS);
+ mti->mti_flags = dev_type | LDD_F_PARAM;
+ mutex_lock(&fsdb->fsdb_mutex);
+ rc = mgs_write_log_param(env, mgs, fsdb, mti, mti->mti_params);
+ mutex_unlock(&fsdb->fsdb_mutex);
+ mgs_revoke_lock(mgs, fsdb, CONFIG_T_CONFIG);
+
+out:
+ if (fsdb)
+ mgs_put_fsdb(mgs, fsdb);
+
+ RETURN(rc);
+}
+
+static int mgs_set_param2(const struct lu_env *env, struct mgs_device *mgs,
+ struct mgs_target_info *mti, const char *param)
+{
+ struct fs_db *fsdb = NULL;
+ int dev_type;
+ size_t len;
+ int rc;
+
+ if (strlcpy(mti->mti_params, param, sizeof(mti->mti_params)) >=
+ sizeof(mti->mti_params))
+ GOTO(out, rc = -E2BIG);
+
+ /* obdname2fsname reports devname as an obd device */
+ len = strcspn(param, ".=");
+ if (len && param[len] != '=') {
+ char *ptr;
+
+ param += len + 1;
+ ptr = strchr(param, '.');
+
+ len = strlen(param);
+ if (ptr)
+ len -= strlen(ptr);
+ if (len >= sizeof(mti->mti_svname))
+ GOTO(out, rc = -E2BIG);
+
+ snprintf(mti->mti_svname, sizeof(mti->mti_svname), "%.*s",
+ (int)len, param);
+
+ obdname2fsname(mti->mti_svname, mti->mti_fsname,
+ sizeof(mti->mti_fsname));
} else {
- mti->mti_flags = rc | LDD_F_PARAM;
- mutex_lock(&fsdb->fsdb_mutex);
- rc = mgs_write_log_param(env, mgs, fsdb, mti, mti->mti_params);
- mutex_unlock(&fsdb->fsdb_mutex);
- mgs_revoke_lock(mgs, fsdb, CONFIG_T_CONFIG);
+ snprintf(mti->mti_svname, sizeof(mti->mti_svname), "general");
}
+ CDEBUG(D_MGS, "set_param2 fs='%s' device='%s' param='%s'\n",
+ mti->mti_fsname, mti->mti_svname, mti->mti_params);
+
+ /* The return value should be the device type i.e LDD_F_SV_TYPE_XXX.
+ * A returned error tells us we don't have a target obd device.
+ */
+ dev_type = server_name2index(mti->mti_svname, &mti->mti_stripe_index,
+ NULL);
+ if (dev_type < 0)
+ dev_type = 0;
+
+ /* the return value should be the device type i.e LDD_F_SV_TYPE_XXX.
+ * Strip -osc or -mdc suffix from svname
+ */
+ if ((dev_type & LDD_F_SV_TYPE_OST || dev_type & LDD_F_SV_TYPE_MDT) &&
+ server_make_name(dev_type, mti->mti_stripe_index,
+ mti->mti_fsname, mti->mti_svname,
+ sizeof(mti->mti_svname)))
+ GOTO(out, rc = -EINVAL);
+
+ rc = mgs_find_or_make_fsdb(env, mgs, PARAMS_FILENAME, &fsdb);
+ if (rc)
+ GOTO(out, rc);
+ /*
+ * Revoke lock so everyone updates. Should be alright if
+ * someone was already reading while we were updating the logs,
+ * so we don't really need to hold the lock while we're
+ * writing (above).
+ */
+ mti->mti_flags = dev_type | LDD_F_PARAM2;
+ mutex_lock(&fsdb->fsdb_mutex);
+ rc = mgs_write_log_param2(env, mgs, fsdb, mti, mti->mti_params);
+ mutex_unlock(&fsdb->fsdb_mutex);
+ mgs_revoke_lock(mgs, fsdb, CONFIG_T_PARAMS);
+ mgs_put_fsdb(mgs, fsdb);
out:
- if (mti)
- OBD_FREE_PTR(mti);
+ RETURN(rc);
+}
- if (fsdb) {
- if (free)
- mgs_unlink_fsdb(mgs, fsdb);
- mgs_put_fsdb(mgs, fsdb);
+/* Set a permanent (config log) param for a target or fs
+ *
+ * @lcfg buf0 may contain the device (testfs-MDT0000) name
+ * buf1 contains the single parameter
+ */
+int mgs_set_param(const struct lu_env *env, struct mgs_device *mgs,
+ struct lustre_cfg *lcfg)
+{
+ const char *param = lustre_cfg_string(lcfg, 1);
+ struct mgs_target_info *mti;
+ int rc;
+
+ /* Create a fake mti to hold everything */
+ OBD_ALLOC_PTR(mti);
+ if (!mti)
+ return -ENOMEM;
+
+ print_lustre_cfg(lcfg);
+
+ if (lcfg->lcfg_command == LCFG_PARAM) {
+ /* For the case of lctl conf_param devname can be
+ * lustre, lustre-mdtlov, lustre-client, lustre-MDT0000
+ */
+ const char *devname = lustre_cfg_string(lcfg, 0);
+
+ rc = mgs_set_conf_param(env, mgs, mti, devname, param);
+ } else {
+ /* In the case of lctl set_param -P lcfg[0] will always
+ * be 'general'. At least for now.
+ */
+ rc = mgs_set_param2(env, mgs, mti, param);
}
- RETURN(rc);
+ OBD_FREE_PTR(mti);
+
+ return rc;
}
static int mgs_write_log_pool(const struct lu_env *env,
bool_switch = simple_strtoul(param, NULL, 10);
rc = nodemap_set_deny_unknown(nodemap_name, bool_switch);
break;
+ case LCFG_NODEMAP_AUDIT_MODE:
+ rc = kstrtoul(param, 10, (unsigned long *)&bool_switch);
+ if (rc == 0)
+ rc = nodemap_set_audit_mode(nodemap_name, bool_switch);
+ break;
+ case LCFG_NODEMAP_MAP_MODE:
+ if (strcmp("both", param) == 0)
+ rc = nodemap_set_mapping_mode(nodemap_name,
+ NODEMAP_MAP_BOTH);
+ else if (strcmp("uid_only", param) == 0)
+ rc = nodemap_set_mapping_mode(nodemap_name,
+ NODEMAP_MAP_UID_ONLY);
+ else if (strcmp("gid_only", param) == 0)
+ rc = nodemap_set_mapping_mode(nodemap_name,
+ NODEMAP_MAP_GID_ONLY);
+ else
+ rc = -EINVAL;
+ break;
case LCFG_NODEMAP_TRUSTED:
bool_switch = simple_strtoul(param, NULL, 10);
rc = nodemap_set_trust_client_ids(nodemap_name, bool_switch);