KERNEL=="obd", MODE="0666"
+# set sysfs values on client
+SUBSYSTEM=="lustre", ACTION=="change", ENV{PARAM}=="?*", RUN+="/usr/sbin/lctl set_param $env{PARAM}=$env{SETTING}"
const char *new_name);
void print_lustre_cfg(struct lustre_cfg *lcfg);
int class_process_config(struct lustre_cfg *lcfg);
+ssize_t class_set_global(const char *param);
+ssize_t class_modify_config(struct lustre_cfg *lcfg, const char *prefix,
+ struct kobject *kobj);
int class_process_proc_param(char *prefix, struct lprocfs_vars *lvars,
struct lustre_cfg *lcfg, void *data);
int class_attach(struct lustre_cfg *lcfg);
int lustre_unregister_fs(void);
int lustre_check_exclusion(struct super_block *sb, char *svname);
-/* sysctl.c */
-extern int obd_sysctl_init(void);
-extern void obd_sysctl_clean(void);
-
typedef __u8 class_uuid_t[16];
static inline void class_uuid_unparse(class_uuid_t uu, struct obd_uuid *out)
{
MODULES := obdclass llog_test
-obdclass-linux-objs := linux-module.o linux-obdo.o linux-sysctl.o
+obdclass-linux-objs := linux-module.o linux-obdo.o
obdclass-linux-objs := $(addprefix linux/,$(obdclass-linux-objs))
default: all
lu_global_fini();
cleanup_class_procfs:
- obd_sysctl_clean();
class_procfs_clean();
cleanup_caches:
lu_global_fini();
obd_cleanup_caches();
- obd_sysctl_clean();
class_procfs_clean();
EXTRA_DIST = \
linux-module.c \
- linux-sysctl.c \
linux-obdo.c
.fops = &obd_psdev_fops,
};
+struct static_lustre_uintvalue_attr {
+ struct {
+ struct attribute attr;
+ ssize_t (*show)(struct kobject *kobj, struct attribute *attr,
+ char *buf);
+ ssize_t (*store)(struct kobject *kobj, struct attribute *attr,
+ const char *buf, size_t len);
+ } u;
+ int *value;
+};
+
+static ssize_t static_uintvalue_show(struct kobject *kobj,
+ struct attribute *attr,
+ char *buf)
+{
+ struct static_lustre_uintvalue_attr *lattr = (void *)attr;
+
+ return sprintf(buf, "%d\n", *lattr->value);
+}
+
+static ssize_t static_uintvalue_store(struct kobject *kobj,
+ struct attribute *attr,
+ const char *buffer, size_t count)
+{
+ struct static_lustre_uintvalue_attr *lattr = (void *)attr;
+ unsigned int val;
+ int rc;
+
+ rc = kstrtouint(buffer, 10, &val);
+ if (rc)
+ return rc;
+
+ *lattr->value = val;
+
+ return count;
+}
+
+#define LUSTRE_STATIC_UINT_ATTR(name, value) \
+static struct static_lustre_uintvalue_attr lustre_sattr_##name = \
+ { __ATTR(name, 0644, static_uintvalue_show, \
+ static_uintvalue_store), value }
+
+LUSTRE_STATIC_UINT_ATTR(timeout, &obd_timeout);
+LUSTRE_STATIC_UINT_ATTR(debug_peer_on_timeout, &obd_debug_peer_on_timeout);
+LUSTRE_STATIC_UINT_ATTR(dump_on_timeout, &obd_dump_on_timeout);
+LUSTRE_STATIC_UINT_ATTR(dump_on_eviction, &obd_dump_on_eviction);
+LUSTRE_STATIC_UINT_ATTR(at_min, &at_min);
+LUSTRE_STATIC_UINT_ATTR(at_max, &at_max);
+LUSTRE_STATIC_UINT_ATTR(at_extra, &at_extra);
+LUSTRE_STATIC_UINT_ATTR(at_early_margin, &at_early_margin);
+LUSTRE_STATIC_UINT_ATTR(at_history, &at_history);
+
+#ifdef HAVE_SERVER_SUPPORT
+LUSTRE_STATIC_UINT_ATTR(ldlm_timeout, &ldlm_timeout);
+LUSTRE_STATIC_UINT_ATTR(bulk_timeout, &bulk_timeout);
+#endif
+
+static ssize_t memused_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%llu\n", obd_memory_sum());
+}
+LUSTRE_RO_ATTR(memused);
+
+static ssize_t memused_max_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%llu\n", obd_memory_max());
+}
+LUSTRE_RO_ATTR(memused_max);
+
+static ssize_t max_dirty_mb_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%lu\n",
+ obd_max_dirty_pages / (1 << (20 - PAGE_SHIFT)));
+}
+
+static ssize_t max_dirty_mb_store(struct kobject *kobj, struct attribute *attr,
+ const char *buffer, size_t count)
+{
+ unsigned long val;
+ int rc;
+
+ rc = kstrtoul(buffer, 10, &val);
+ if (rc)
+ return rc;
+
+ val *= 1 << (20 - PAGE_SHIFT); /* convert to pages */
+
+ if (val > ((totalram_pages / 10) * 9)) {
+ /* Somebody wants to assign too much memory to dirty pages */
+ return -EINVAL;
+ }
+
+ if (val < 4 << (20 - PAGE_SHIFT)) {
+ /* Less than 4 Mb for dirty cache is also bad */
+ return -EINVAL;
+ }
+
+ obd_max_dirty_pages = val;
+
+ return count;
+}
+LUSTRE_RW_ATTR(max_dirty_mb);
+
static ssize_t version_show(struct kobject *kobj, struct attribute *attr,
char *buf)
{
&lustre_attr_health_check.attr,
&lustre_attr_jobid_name.attr,
&lustre_attr_jobid_var.attr,
+ &lustre_sattr_timeout.u.attr,
+ &lustre_attr_max_dirty_mb.attr,
+ &lustre_sattr_debug_peer_on_timeout.u.attr,
+ &lustre_sattr_dump_on_timeout.u.attr,
+ &lustre_sattr_dump_on_eviction.u.attr,
+ &lustre_sattr_at_min.u.attr,
+ &lustre_sattr_at_max.u.attr,
+ &lustre_sattr_at_extra.u.attr,
+ &lustre_sattr_at_early_margin.u.attr,
+ &lustre_sattr_at_history.u.attr,
+ &lustre_attr_memused_max.attr,
+ &lustre_attr_memused.attr,
+#ifdef HAVE_SERVER_SUPPORT
+ &lustre_sattr_ldlm_timeout.u.attr,
+ &lustre_sattr_bulk_timeout.u.attr,
+#endif
NULL,
};
.attrs = lustre_attrs,
};
+ssize_t class_set_global(const char *param)
+{
+ const char *value = strchr(param, '=') + 1;
+ size_t off = value - param - 1;
+ ssize_t count = -ENOENT;
+ int i;
+
+ for (i = 0; lustre_attrs[i]; i++) {
+ if (!strncmp(lustre_attrs[i]->name, param, off)) {
+ count = lustre_attr_store(&lustre_kset->kobj,
+ lustre_attrs[i], value,
+ strlen(value));
+ break;
+ }
+ }
+ return count;
+}
+
int class_procfs_init(void)
{
struct proc_dir_entry *entry;
goto out;
}
- rc = obd_sysctl_init();
- if (rc) {
- kset_unregister(lustre_kset);
- goto out;
- }
-
rc = jobid_cache_init();
if (rc) {
kset_unregister(lustre_kset);
+++ /dev/null
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2017, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- */
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/ctype.h>
-#include <linux/bitops.h>
-#include <linux/uaccess.h>
-#include <linux/utsname.h>
-
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <obd_support.h>
-#include <lprocfs_status.h>
-#include <obd_class.h>
-
-struct static_lustre_uintvalue_attr {
- struct {
- struct attribute attr;
- ssize_t (*show)(struct kobject *kobj, struct attribute *attr,
- char *buf);
- ssize_t (*store)(struct kobject *kobj, struct attribute *attr,
- const char *buf, size_t len);
- } u;
- int *value;
-};
-
-static ssize_t static_uintvalue_show(struct kobject *kobj,
- struct attribute *attr,
- char *buf)
-{
- struct static_lustre_uintvalue_attr *lattr = (void *)attr;
-
- return sprintf(buf, "%d\n", *lattr->value);
-}
-
-static ssize_t static_uintvalue_store(struct kobject *kobj,
- struct attribute *attr,
- const char *buffer, size_t count)
-{
- struct static_lustre_uintvalue_attr *lattr = (void *)attr;
- unsigned int val;
- int rc;
-
- rc = kstrtouint(buffer, 10, &val);
- if (rc)
- return rc;
-
- *lattr->value = val;
-
- return count;
-}
-
-#define LUSTRE_STATIC_UINT_ATTR(name, value) \
-static struct static_lustre_uintvalue_attr lustre_sattr_##name = \
- {__ATTR(name, 0644, \
- static_uintvalue_show, \
- static_uintvalue_store),\
- value }
-
-LUSTRE_STATIC_UINT_ATTR(timeout, &obd_timeout);
-
-static ssize_t max_dirty_mb_show(struct kobject *kobj, struct attribute *attr,
- char *buf)
-{
- return sprintf(buf, "%lu\n",
- obd_max_dirty_pages / (1 << (20 - PAGE_SHIFT)));
-}
-
-static ssize_t max_dirty_mb_store(struct kobject *kobj, struct attribute *attr,
- const char *buffer, size_t count)
-{
- unsigned long val;
- int rc;
-
- rc = kstrtoul(buffer, 10, &val);
- if (rc)
- return rc;
-
- val *= 1 << (20 - PAGE_SHIFT); /* convert to pages */
-
- if (val > ((totalram_pages / 10) * 9)) {
- /* Somebody wants to assign too much memory to dirty pages */
- return -EINVAL;
- }
-
- if (val < 4 << (20 - PAGE_SHIFT)) {
- /* Less than 4 Mb for dirty cache is also bad */
- return -EINVAL;
- }
-
- obd_max_dirty_pages = val;
-
- return count;
-}
-LUSTRE_RW_ATTR(max_dirty_mb);
-
-LUSTRE_STATIC_UINT_ATTR(debug_peer_on_timeout, &obd_debug_peer_on_timeout);
-LUSTRE_STATIC_UINT_ATTR(dump_on_timeout, &obd_dump_on_timeout);
-LUSTRE_STATIC_UINT_ATTR(dump_on_eviction, &obd_dump_on_eviction);
-LUSTRE_STATIC_UINT_ATTR(at_min, &at_min);
-LUSTRE_STATIC_UINT_ATTR(at_max, &at_max);
-LUSTRE_STATIC_UINT_ATTR(at_extra, &at_extra);
-LUSTRE_STATIC_UINT_ATTR(at_early_margin, &at_early_margin);
-LUSTRE_STATIC_UINT_ATTR(at_history, &at_history);
-
-#ifdef HAVE_SERVER_SUPPORT
-LUSTRE_STATIC_UINT_ATTR(ldlm_timeout, &ldlm_timeout);
-LUSTRE_STATIC_UINT_ATTR(bulk_timeout, &bulk_timeout);
-#endif
-
-static ssize_t memused_show(struct kobject *kobj, struct attribute *attr,
- char *buf)
-{
- return sprintf(buf, "%llu\n", obd_memory_sum());
-}
-LUSTRE_RO_ATTR(memused);
-
-static ssize_t memused_max_show(struct kobject *kobj, struct attribute *attr,
- char *buf)
-{
- return sprintf(buf, "%llu\n", obd_memory_max());
-}
-LUSTRE_RO_ATTR(memused_max);
-
-static struct attribute *lustre_attrs[] = {
- &lustre_sattr_timeout.u.attr,
- &lustre_attr_max_dirty_mb.attr,
- &lustre_sattr_debug_peer_on_timeout.u.attr,
- &lustre_sattr_dump_on_timeout.u.attr,
- &lustre_sattr_dump_on_eviction.u.attr,
- &lustre_sattr_at_min.u.attr,
- &lustre_sattr_at_max.u.attr,
- &lustre_sattr_at_extra.u.attr,
- &lustre_sattr_at_early_margin.u.attr,
- &lustre_sattr_at_history.u.attr,
- &lustre_attr_memused_max.attr,
- &lustre_attr_memused.attr,
-#ifdef HAVE_SERVER_SUPPORT
- &lustre_sattr_ldlm_timeout.u.attr,
- &lustre_sattr_bulk_timeout.u.attr,
-#endif
- NULL,
-};
-
-static struct attribute_group lustre_attr_group = {
- .attrs = lustre_attrs,
-};
-
-int obd_sysctl_init(void)
-{
- return sysfs_create_group(&lustre_kset->kobj, &lustre_attr_group);
-}
-
-void obd_sysctl_clean(void)
-{
- sysfs_remove_group(&lustre_kset->kobj, &lustre_attr_group);
-}
#define DEBUG_SUBSYSTEM S_CLASS
+#include <linux/kobject.h>
#include <linux/string.h>
#include <llog_swab.h>
}
EXPORT_SYMBOL(class_del_profiles);
-static int class_set_global(char *ptr, int val, struct lustre_cfg *lcfg)
-{
- ENTRY;
- if (class_match_param(ptr, PARAM_AT_MIN, NULL) == 0)
- at_min = val;
- else if (class_match_param(ptr, PARAM_AT_MAX, NULL) == 0)
- at_max = val;
- else if (class_match_param(ptr, PARAM_AT_EXTRA, NULL) == 0)
- at_extra = val;
- else if (class_match_param(ptr, PARAM_AT_EARLY_MARGIN, NULL) == 0)
- at_early_margin = val;
- else if (class_match_param(ptr, PARAM_AT_HISTORY, NULL) == 0)
- at_history = val;
- else if (class_match_param(ptr, PARAM_JOBID_VAR, NULL) == 0)
- strlcpy(obd_jobid_var, lustre_cfg_string(lcfg, 2),
- JOBSTATS_JOBID_VAR_MAX_LEN + 1);
- else
- RETURN(-EINVAL);
-
- CDEBUG(D_IOCTL, "global %s = %d\n", ptr, val);
- RETURN(0);
-}
-
-
/* We can't call ll_process_config or lquota_process_config directly because
- * it lives in a module that must be loaded after this one. */
+ * it lives in a module that must be loaded after this one.
+ */
static int (*client_process_config)(struct lustre_cfg *lcfg) = NULL;
+#ifdef HAVE_SERVER_SUPPORT
static int (*quota_process_config)(struct lustre_cfg *lcfg) = NULL;
+#endif /* HAVE_SERVER_SUPPORT */
void lustre_register_client_process_config(int (*cpc)(struct lustre_cfg *lcfg))
{
}
EXPORT_SYMBOL(lustre_cfg_rename);
-static int process_param2_config(struct lustre_cfg *lcfg)
+static ssize_t process_param2_config(struct lustre_cfg *lcfg)
{
char *param = lustre_cfg_string(lcfg, 1);
char *upcall = lustre_cfg_string(lcfg, 2);
+ struct kobject *kobj = NULL;
+ const char *subsys = param;
char *argv[] = {
[0] = "/usr/sbin/lctl",
[1] = "set_param",
};
ktime_t start;
ktime_t end;
- int rc;
+ size_t len;
+ int rc;
+
ENTRY;
+ print_lustre_cfg(lcfg);
+
+ len = strcspn(param, ".=");
+ if (!len)
+ return -EINVAL;
+
+ /* If we find '=' then its the top level sysfs directory */
+ if (param[len] == '=')
+ return class_set_global(param);
+
+ subsys = kstrndup(param, len, GFP_KERNEL);
+ if (!subsys)
+ return -ENOMEM;
+
+ kobj = kset_find_obj(lustre_kset, subsys);
+ kfree(subsys);
+ if (kobj) {
+ char *value = param;
+ char *envp[3];
+ int i;
+
+ param = strsep(&value, "=");
+ envp[0] = kasprintf(GFP_KERNEL, "PARAM=%s", param);
+ envp[1] = kasprintf(GFP_KERNEL, "SETTING=%s", value);
+ envp[2] = NULL;
+
+ rc = kobject_uevent_env(kobj, KOBJ_CHANGE, envp);
+ for (i = 0; i < ARRAY_SIZE(envp); i++)
+ kfree(envp[i]);
+
+ kobject_put(kobj);
+
+ RETURN(rc);
+ }
/* Add upcall processing here. Now only lctl is supported */
if (strcmp(upcall, LCTL_UPCALL) != 0) {
RETURN(rc);
}
+#ifdef HAVE_SERVER_SUPPORT
void lustre_register_quota_process_config(int (*qpc)(struct lustre_cfg *lcfg))
{
quota_process_config = qpc;
}
EXPORT_SYMBOL(lustre_register_quota_process_config);
+#endif /* HAVE_SERVER_SUPPORT */
/** Process configuration commands given in lustre_cfg form.
* These may come from direct calls (e.g. class_manual_cleanup)
} else if ((class_match_param(lustre_cfg_string(lcfg, 1),
PARAM_SYS, &tmp) == 0)) {
/* Global param settings */
- err = class_set_global(tmp, lcfg->lcfg_num, lcfg);
+ err = class_set_global(tmp);
/*
* Client or server should not fail to mount if
* it hits an unknown configuration parameter.
*/
- if (err != 0)
+ if (err < 0)
CWARN("Ignoring unknown param %s\n", tmp);
GOTO(out, err = 0);
+#ifdef HAVE_SERVER_SUPPORT
} else if ((class_match_param(lustre_cfg_string(lcfg, 1),
PARAM_QUOTA, &tmp) == 0) &&
quota_process_config) {
err = (*quota_process_config)(lcfg);
GOTO(out, err);
+#endif /* HAVE_SERVER_SUPPORT */
}
break;
}
EXPORT_SYMBOL(class_process_config);
+ssize_t class_modify_config(struct lustre_cfg *lcfg, const char *prefix,
+ struct kobject *kobj)
+{
+ struct kobj_type *typ;
+ ssize_t count = 0;
+ int i;
+
+ if (lcfg->lcfg_command != LCFG_PARAM) {
+ CERROR("Unknown command: %d\n", lcfg->lcfg_command);
+ return -EINVAL;
+ }
+
+ typ = get_ktype(kobj);
+ if (!typ || !typ->default_attrs)
+ return -ENODEV;
+
+ print_lustre_cfg(lcfg);
+
+ /*
+ * 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++) {
+ struct attribute *attr;
+ size_t keylen;
+ char *value;
+ char *key;
+ int j;
+
+ 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;
+
+ value = strchr(key, '=');
+ if (!value || *(value + 1) == 0) {
+ CERROR("%s: can't parse param '%s' (missing '=')\n",
+ lustre_cfg_string(lcfg, 0),
+ lustre_cfg_string(lcfg, i));
+ /* continue parsing other params */
+ continue;
+ }
+ keylen = value - key;
+ value++;
+
+ attr = NULL;
+ for (j = 0; typ->default_attrs[j]; j++) {
+ if (!strncmp(typ->default_attrs[j]->name, key,
+ keylen)) {
+ attr = typ->default_attrs[j];
+ break;
+ }
+ }
+
+ if (!attr) {
+ char *envp[3];
+
+ envp[0] = kasprintf(GFP_KERNEL, "PARAM=%s.%s.%.*s",
+ kobject_name(kobj->parent),
+ kobject_name(kobj),
+ (int) keylen, key);
+ envp[1] = kasprintf(GFP_KERNEL, "SETTING=%s", value);
+ envp[2] = NULL;
+
+ if (kobject_uevent_env(kobj, KOBJ_CHANGE, envp)) {
+ CERROR("%s: failed to send uevent %s\n",
+ kobject_name(kobj), key);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(envp); i++)
+ kfree(envp[i]);
+ } else {
+ count += lustre_attr_store(kobj, attr, value,
+ strlen(value));
+ }
+ }
+ return count;
+}
+EXPORT_SYMBOL(class_modify_config);
+
int class_process_proc_param(char *prefix, struct lprocfs_vars *lvars,
struct lustre_cfg *lcfg, void *data)
{