#ifdef __KERNEL__
#include <obd_class.h>
#include <linux/string.h>
+#include <lustre_disk.h>
#else
#include <liblustre.h>
#include <string.h>
#include <obd_class.h>
#include <obd.h>
#endif
+#include <lustre_ioctl.h>
#include <lustre_log.h>
#include <lprocfs_status.h>
#include <lustre_param.h>
/* recovery data */
cfs_init_timer(&obd->obd_recovery_timer);
spin_lock_init(&obd->obd_recovery_task_lock);
- cfs_waitq_init(&obd->obd_next_transno_waitq);
- cfs_waitq_init(&obd->obd_evict_inprogress_waitq);
- CFS_INIT_LIST_HEAD(&obd->obd_req_replay_queue);
- CFS_INIT_LIST_HEAD(&obd->obd_lock_replay_queue);
- CFS_INIT_LIST_HEAD(&obd->obd_final_req_queue);
- CFS_INIT_LIST_HEAD(&obd->obd_evict_list);
+ init_waitqueue_head(&obd->obd_next_transno_waitq);
+ init_waitqueue_head(&obd->obd_evict_inprogress_waitq);
+ CFS_INIT_LIST_HEAD(&obd->obd_req_replay_queue);
+ CFS_INIT_LIST_HEAD(&obd->obd_lock_replay_queue);
+ CFS_INIT_LIST_HEAD(&obd->obd_final_req_queue);
+ CFS_INIT_LIST_HEAD(&obd->obd_evict_list);
+ INIT_LIST_HEAD(&obd->obd_lwp_list);
- llog_group_init(&obd->obd_olg, FID_SEQ_LLOG);
+ llog_group_init(&obd->obd_olg);
obd->obd_conn_inprogress = 0;
}
memcpy(obd->obd_uuid.uuid, uuid, len);
- /* do the attach */
- if (OBP(obd, attach)) {
- rc = OBP(obd,attach)(obd, sizeof *lcfg, lcfg);
- if (rc)
- GOTO(out, rc = -EINVAL);
- }
-
/* Detach drops this */
spin_lock(&obd->obd_dev_lock);
- cfs_atomic_set(&obd->obd_refcount, 1);
+ atomic_set(&obd->obd_refcount, 1);
spin_unlock(&obd->obd_dev_lock);
lu_ref_init(&obd->obd_reference);
lu_ref_add(&obd->obd_reference, "attach", obd);
obd->obd_attached = 1;
CDEBUG(D_IOCTL, "OBD: dev %d attached type %s with refcount %d\n",
- obd->obd_minor, typename, cfs_atomic_read(&obd->obd_refcount));
+ obd->obd_minor, typename, atomic_read(&obd->obd_refcount));
RETURN(0);
out:
if (obd != NULL) {
}
/* Leave this on forever */
obd->obd_stopping = 1;
+ spin_unlock(&obd->obd_dev_lock);
/* wait for already-arrived-connections to finish. */
- while (obd->obd_conn_inprogress > 0) {
- spin_unlock(&obd->obd_dev_lock);
-
- cfs_cond_resched();
-
- spin_lock(&obd->obd_dev_lock);
- }
- spin_unlock(&obd->obd_dev_lock);
+ while (obd->obd_conn_inprogress > 0)
+ yield();
+ smp_rmb();
if (lcfg->lcfg_bufcount >= 2 && LUSTRE_CFG_BUFLEN(lcfg, 1) > 0) {
for (flag = lustre_cfg_string(lcfg, 1); *flag != 0; flag++)
/* The three references that should be remaining are the
* obd_self_export and the attach and setup references. */
- if (cfs_atomic_read(&obd->obd_refcount) > 3) {
+ if (atomic_read(&obd->obd_refcount) > 3) {
/* refcounf - 3 might be the number of real exports
(excluding self export). But class_incref is called
by other things as well, so don't count on it. */
CDEBUG(D_IOCTL, "%s: forcing exports to disconnect: %d\n",
- obd->obd_name, cfs_atomic_read(&obd->obd_refcount) - 3);
+ obd->obd_name, atomic_read(&obd->obd_refcount) - 3);
dump_exports(obd, 0);
class_disconnect_exports(obd);
}
const char *scope, const void *source)
{
lu_ref_add_atomic(&obd->obd_reference, scope, source);
- cfs_atomic_inc(&obd->obd_refcount);
+ atomic_inc(&obd->obd_refcount);
CDEBUG(D_INFO, "incref %s (%p) now %d\n", obd->obd_name, obd,
- cfs_atomic_read(&obd->obd_refcount));
+ atomic_read(&obd->obd_refcount));
return obd;
}
int refs;
spin_lock(&obd->obd_dev_lock);
- cfs_atomic_dec(&obd->obd_refcount);
- refs = cfs_atomic_read(&obd->obd_refcount);
+ atomic_dec(&obd->obd_refcount);
+ refs = atomic_read(&obd->obd_refcount);
spin_unlock(&obd->obd_dev_lock);
lu_ref_del(&obd->obd_reference, scope, source);
CERROR("Cleanup %s returned %d\n",
obd->obd_name, err);
}
- if (OBP(obd, detach)) {
- err = OBP(obd, detach)(obd);
- if (err)
- CERROR("Detach returned %d\n", err);
- }
+
class_release_dev(obd);
}
}
}
case LCFG_SET_PARAM: {
err = process_param2_config(lcfg);
- GOTO(out, 0);
+ GOTO(out, err = 0);
}
}
/* Commands that require a device */
}
EXPORT_SYMBOL(class_process_config);
+#ifndef HAVE_ONLY_PROCFS_SEQ
int class_process_proc_param(char *prefix, struct lprocfs_vars *lvars,
struct lustre_cfg *lcfg, void *data)
{
for (i = 1; i < lcfg->lcfg_bufcount; i++) {
key = lustre_cfg_buf(lcfg, i);
/* Strip off prefix */
- class_match_param(key, prefix, &key);
+ if (class_match_param(key, prefix, &key))
+ /* If the prefix doesn't match, return error so we
+ * can pass it down the stack */
+ RETURN(-ENOSYS);
sval = strchr(key, '=');
if (!sval || (*(sval + 1) == 0)) {
CERROR("Can't parse param %s (missing '=')\n", key);
keylen == strlen(var->name)) {
matched++;
rc = -EROFS;
- if (var->write_fptr) {
- mm_segment_t oldfs;
- oldfs = get_fs();
- set_fs(KERNEL_DS);
- rc = (var->write_fptr)(NULL, sval,
- vallen, data);
- set_fs(oldfs);
- }
- break;
+
+ if (var->write_fptr) {
+ mm_segment_t oldfs;
+ oldfs = get_fs();
+ set_fs(KERNEL_DS);
+ rc = (var->write_fptr)(NULL, sval,
+ vallen, data);
+ set_fs(oldfs);
+ }
+ break;
}
j++;
}
- if (!matched) {
- /* If the prefix doesn't match, return error so we
- can pass it down the stack */
- if (strnchr(key, keylen, '.'))
- RETURN(-ENOSYS);
- CERROR("%s: unknown param %s\n",
- (char *)lustre_cfg_string(lcfg, 0), key);
- /* rc = -EINVAL; continue parsing other params */
- skip++;
- } else if (rc < 0) {
- CERROR("writing proc entry %s err %d\n",
- var->name, rc);
- rc = 0;
+ if (!matched) {
+ CERROR("%.*s: %s unknown param %s\n",
+ (int)strlen(prefix) - 1, prefix,
+ (char *)lustre_cfg_string(lcfg, 0), key);
+ /* rc = -EINVAL; continue parsing other params */
+ skip++;
+ } else if (rc < 0) {
+ CERROR("%s: error writing proc entry '%s': rc = %d\n",
+ prefix, var->name, rc);
+ rc = 0;
} else {
CDEBUG(D_CONFIG, "%s.%.*s: Set parameter %.*s=%s\n",
lustre_cfg_string(lcfg, 0),
#endif
}
EXPORT_SYMBOL(class_process_proc_param);
+#endif
+
+int class_process_proc_seq_param(char *prefix, struct lprocfs_seq_vars *lvars,
+ struct lustre_cfg *lcfg, void *data)
+{
+#ifdef __KERNEL__
+ struct lprocfs_seq_vars *var;
+ struct file fakefile;
+ struct seq_file fake_seqfile;
+ char *key, *sval;
+ int i, keylen, vallen;
+ int matched = 0, j = 0;
+ int rc = 0;
+ int skip = 0;
+ ENTRY;
+
+ if (lcfg->lcfg_command != LCFG_PARAM) {
+ CERROR("Unknown command: %d\n", lcfg->lcfg_command);
+ RETURN(-EINVAL);
+ }
+
+ /* fake a seq file so that var->fops->write can work... */
+ fakefile.private_data = &fake_seqfile;
+ fake_seqfile.private = data;
+ /* e.g. tunefs.lustre --param mdt.group_upcall=foo /r/tmp/lustre-mdt
+ or lctl conf_param lustre-MDT0000.mdt.group_upcall=bar
+ or lctl conf_param lustre-OST0000.osc.max_dirty_mb=36 */
+ for (i = 1; i < lcfg->lcfg_bufcount; i++) {
+ key = lustre_cfg_buf(lcfg, i);
+ /* Strip off prefix */
+ if (class_match_param(key, prefix, &key))
+ /* If the prefix doesn't match, return error so we
+ * can pass it down the stack */
+ RETURN(-ENOSYS);
+ sval = strchr(key, '=');
+ if (!sval || (*(sval + 1) == 0)) {
+ CERROR("Can't parse param %s (missing '=')\n", key);
+ /* rc = -EINVAL; continue parsing other params */
+ continue;
+ }
+ keylen = sval - key;
+ sval++;
+ vallen = strlen(sval);
+ matched = 0;
+ j = 0;
+ /* Search proc entries */
+ while (lvars[j].name) {
+ var = &lvars[j];
+ if (class_match_param(key, (char *)var->name, 0) == 0 &&
+ keylen == strlen(var->name)) {
+ matched++;
+ rc = -EROFS;
+
+ if (var->fops && var->fops->write) {
+ mm_segment_t oldfs;
+ oldfs = get_fs();
+ set_fs(KERNEL_DS);
+ rc = (var->fops->write)(&fakefile, sval,
+ vallen, NULL);
+ set_fs(oldfs);
+ }
+ break;
+ }
+ j++;
+ }
+ if (!matched) {
+ CERROR("%.*s: %s unknown param %s\n",
+ (int)strlen(prefix) - 1, prefix,
+ (char *)lustre_cfg_string(lcfg, 0), key);
+ /* rc = -EINVAL; continue parsing other params */
+ skip++;
+ } else if (rc < 0) {
+ CERROR("%s: error writing proc entry '%s': rc = %d\n",
+ prefix, var->name, rc);
+ rc = 0;
+ } else {
+ CDEBUG(D_CONFIG, "%s.%.*s: Set parameter %.*s=%s\n",
+ lustre_cfg_string(lcfg, 0),
+ (int)strlen(prefix) - 1, prefix,
+ (int)(sval - key - 1), key, sval);
+ }
+ }
+
+ if (rc > 0)
+ rc = 0;
+ if (!rc && skip)
+ rc = skip;
+ RETURN(rc);
+#else
+ CDEBUG(D_CONFIG, "liblustre can't process params.\n");
+ /* Don't throw config error */
+ RETURN(0);
+#endif
+}
+EXPORT_SYMBOL(class_process_proc_seq_param);
#ifdef __KERNEL__
extern int lustre_check_exclusion(struct super_block *sb, char *svname);
#define lustre_check_exclusion(a,b) 0
#endif
+/*
+ * Supplemental functions for config logs, it allocates lustre_cfg
+ * buffers plus initialized llog record header at the beginning.
+ */
+struct llog_cfg_rec *lustre_cfg_rec_new(int cmd, struct lustre_cfg_bufs *bufs)
+{
+ struct llog_cfg_rec *lcr;
+ int reclen;
+
+ ENTRY;
+
+ reclen = lustre_cfg_len(bufs->lcfg_bufcount, bufs->lcfg_buflen);
+ reclen = llog_data_len(reclen) + sizeof(struct llog_rec_hdr) +
+ sizeof(struct llog_rec_tail);
+
+ OBD_ALLOC(lcr, reclen);
+ if (lcr == NULL)
+ RETURN(NULL);
+
+ lustre_cfg_init(&lcr->lcr_cfg, cmd, bufs);
+
+ lcr->lcr_hdr.lrh_len = reclen;
+ lcr->lcr_hdr.lrh_type = OBD_CFG_REC;
+
+ RETURN(lcr);
+}
+EXPORT_SYMBOL(lustre_cfg_rec_new);
+
+void lustre_cfg_rec_free(struct llog_cfg_rec *lcr)
+{
+ ENTRY;
+ OBD_FREE(lcr, lcr->lcr_hdr.lrh_len);
+ EXIT;
+}
+EXPORT_SYMBOL(lustre_cfg_rec_free);
+
/** Parse a configuration llog, doing various manipulations on them
* for various reasons, (modifications for compatibility, skip obsolete
* records, change uuids, etc), then class_process_config() resulting
if (marker->cm_flags & CM_START) {
/* all previous flags off */
clli->cfg_flags = CFG_F_MARKER;
+ server_name2index(marker->cm_tgtname,
+ &clli->cfg_lwp_idx, NULL);
if (marker->cm_flags & CM_SKIP) {
clli->cfg_flags |= CFG_F_SKIP;
CDEBUG(D_CONFIG, "SKIP #%d\n",
}
lcfg_new = lustre_cfg_new(lcfg->lcfg_command, &bufs);
+ if (lcfg_new == NULL)
+ GOTO(out, rc = -ENOMEM);
lcfg_new->lcfg_num = lcfg->lcfg_num;
lcfg_new->lcfg_flags = lcfg->lcfg_flags;
}
EXPORT_SYMBOL(class_config_parse_llog);
+struct lcfg_type_data {
+ __u32 ltd_type;
+ char *ltd_name;
+ char *ltd_bufs[4];
+} lcfg_data_table[] = {
+ { LCFG_ATTACH, "attach", { "type", "UUID", "3", "4" } },
+ { LCFG_DETACH, "detach", { "1", "2", "3", "4" } },
+ { LCFG_SETUP, "setup", { "UUID", "node", "options", "failout" } },
+ { LCFG_CLEANUP, "cleanup", { "1", "2", "3", "4" } },
+ { LCFG_ADD_UUID, "add_uuid", { "node", "2", "3", "4" } },
+ { LCFG_DEL_UUID, "del_uuid", { "1", "2", "3", "4" } },
+ { LCFG_MOUNTOPT, "new_profile", { "name", "lov", "lmv", "4" } },
+ { LCFG_DEL_MOUNTOPT, "del_mountopt", { "1", "2", "3", "4" } , },
+ { LCFG_SET_TIMEOUT, "set_timeout", { "parameter", "2", "3", "4" } },
+ { LCFG_SET_UPCALL, "set_upcall", { "1", "2", "3", "4" } },
+ { LCFG_ADD_CONN, "add_conn", { "node", "2", "3", "4" } },
+ { LCFG_DEL_CONN, "del_conn", { "1", "2", "3", "4" } },
+ { LCFG_LOV_ADD_OBD, "add_osc", { "ost", "index", "gen", "UUID" } },
+ { LCFG_LOV_DEL_OBD, "del_osc", { "1", "2", "3", "4" } },
+ { LCFG_PARAM, "set_param", { "parameter", "value", "3", "4" } },
+ { LCFG_MARKER, "marker", { "1", "2", "3", "4" } },
+ { LCFG_LOG_START, "log_start", { "1", "2", "3", "4" } },
+ { LCFG_LOG_END, "log_end", { "1", "2", "3", "4" } },
+ { LCFG_LOV_ADD_INA, "add_osc_inactive", { "1", "2", "3", "4" } },
+ { LCFG_ADD_MDC, "add_mdc", { "mdt", "index", "gen", "UUID" } },
+ { LCFG_DEL_MDC, "del_mdc", { "1", "2", "3", "4" } },
+ { LCFG_SPTLRPC_CONF, "security", { "parameter", "2", "3", "4" } },
+ { LCFG_POOL_NEW, "new_pool", { "fsname", "pool", "3", "4" } },
+ { LCFG_POOL_ADD, "add_pool", { "fsname", "pool", "ost", "4" } },
+ { LCFG_POOL_REM, "remove_pool", { "fsname", "pool", "ost", "4" } },
+ { LCFG_POOL_DEL, "del_pool", { "fsname", "pool", "3", "4" } },
+ { LCFG_SET_LDLM_TIMEOUT, "set_ldlm_timeout",
+ { "parameter", "2", "3", "4" } },
+ { 0, NULL, { NULL, NULL, NULL, NULL } }
+};
+
+static struct lcfg_type_data *lcfg_cmd2data(__u32 cmd)
+{
+ int i = 0;
+
+ while (lcfg_data_table[i].ltd_type != 0) {
+ if (lcfg_data_table[i].ltd_type == cmd)
+ return &lcfg_data_table[i];
+ i++;
+ }
+ return NULL;
+}
+
+/**
+ * parse config record and output dump in supplied buffer.
+ * This is separated from class_config_dump_handler() to use
+ * for ioctl needs as well
+ *
+ * Sample Output:
+ * - { event: attach, device: lustrewt-clilov, type: lov, UUID:
+ * lustrewt-clilov_UUID }
+ */
+int class_config_yaml_output(struct llog_rec_hdr *rec, char *buf, int size)
+{
+ struct lustre_cfg *lcfg = (struct lustre_cfg *)(rec + 1);
+ char *ptr = buf;
+ char *end = buf + size;
+ int rc = 0, i;
+ struct lcfg_type_data *ldata;
+
+ LASSERT(rec->lrh_type == OBD_CFG_REC);
+ rc = lustre_cfg_sanity_check(lcfg, rec->lrh_len);
+ if (rc < 0)
+ return rc;
+
+ ldata = lcfg_cmd2data(lcfg->lcfg_command);
+ if (ldata == NULL)
+ return -ENOTTY;
+
+ if (lcfg->lcfg_command == LCFG_MARKER)
+ return 0;
+
+ /* form YAML entity */
+ ptr += snprintf(ptr, end - ptr, "- { event: %s", ldata->ltd_name);
+
+ if (lcfg->lcfg_flags)
+ ptr += snprintf(ptr, end - ptr, ", flags: %#08x",
+ lcfg->lcfg_flags);
+ if (lcfg->lcfg_num)
+ ptr += snprintf(ptr, end - ptr, ", num: %#08x",
+ lcfg->lcfg_num);
+ if (lcfg->lcfg_nid)
+ ptr += snprintf(ptr, end - ptr, ", nid: %s("LPX64")",
+ libcfs_nid2str(lcfg->lcfg_nid),
+ lcfg->lcfg_nid);
+
+ if (LUSTRE_CFG_BUFLEN(lcfg, 0) > 0)
+ ptr += snprintf(ptr, end - ptr, ", device: %s",
+ lustre_cfg_string(lcfg, 0));
+
+ for (i = 1; i < lcfg->lcfg_bufcount; i++) {
+ if (LUSTRE_CFG_BUFLEN(lcfg, i) > 0)
+ ptr += snprintf(ptr, end - ptr, ", %s: %s",
+ ldata->ltd_bufs[i - 1],
+ lustre_cfg_string(lcfg, i));
+ }
+
+ ptr += snprintf(ptr, end - ptr, " }\n");
+ /* return consumed bytes */
+ rc = ptr - buf;
+ return rc;
+}
+
/**
* parse config record and output dump in supplied buffer.
* This is separated from class_config_dump_handler() to use
lustre_cfg_string(lcfg, i));
}
}
+ ptr += snprintf(ptr, end - ptr, "\n");
/* return consumed bytes */
rc = ptr - buf;
RETURN(rc);