#define module_param(name, type, perm) \
module_param_named(name, name, type, perm)
+/**
+ * kparam_block_sysfs_write - make sure a parameter isn't written via sysfs.
+ * @name: the name of the parameter
+ *
+ * There's no point blocking write on a paramter that isn't writable via sysfs!
+ */
+#define kparam_block_sysfs_write(name) \
+ do { \
+ BUG_ON(!(__param_##name.perm & 0222)); \
+ __kernel_param_lock(); \
+ } while (0)
+
+/**
+ * kparam_unblock_sysfs_write - allows sysfs to write to a parameter again.
+ * @name: the name of the parameter
+ */
+#define kparam_unblock_sysfs_write(name) \
+ do { \
+ BUG_ON(!(__param_##name.perm & 0222)); \
+ __kernel_param_unlock(); \
+ } while (0)
+
+/**
+ * kparam_block_sysfs_read - make sure a parameter isn't read via sysfs.
+ * @name: the name of the parameter
+ *
+ * This also blocks sysfs writes.
+ */
+#define kparam_block_sysfs_read(name) \
+ do { \
+ BUG_ON(!(__param_##name.perm & 0444)); \
+ __kernel_param_lock(); \
+ } while (0)
+
+/**
+ * kparam_unblock_sysfs_read - allows sysfs to read a parameter again.
+ * @name: the name of the parameter
+ */
+#define kparam_unblock_sysfs_read(name) \
+ do { \
+ BUG_ON(!(__param_##name.perm & 0444)); \
+ __kernel_param_unlock(); \
+ } while (0)
+
+#ifdef CONFIG_SYSFS
+extern void __kernel_param_lock(void);
+extern void __kernel_param_unlock(void);
+#else
+static inline void __kernel_param_lock(void)
+{
+}
+static inline void __kernel_param_unlock(void)
+{
+}
+#endif
+
#ifndef MODULE
/**
* core_param - define a historical core kernel parameter.
#define DEBUGP(fmt, a...)
#endif
+/* Protects all parameters, and incidentally kmalloced_param list. */
+static DEFINE_MUTEX(param_lock);
+
/* This just allows us to keep track of which parameters are kmalloced. */
struct kmalloced_param {
struct list_head list;
char val[];
};
-static DEFINE_MUTEX(param_lock);
static LIST_HEAD(kmalloced_params);
static void *kmalloc_parameter(unsigned int size)
if (!p)
return NULL;
- mutex_lock(¶m_lock);
list_add(&p->list, &kmalloced_params);
- mutex_unlock(¶m_lock);
-
return p->val;
}
{
struct kmalloced_param *p;
- mutex_lock(¶m_lock);
list_for_each_entry(p, &kmalloced_params, list) {
if (p->val == param) {
list_del(&p->list);
break;
}
}
- mutex_unlock(¶m_lock);
}
static inline char dash2underscore(char c)
int (*handle_unknown)(char *param, char *val))
{
unsigned int i;
+ int err;
/* Find parameter */
for (i = 0; i < num_params; i++) {
return -EINVAL;
DEBUGP("They are equal! Calling %p\n",
params[i].ops->set);
- return params[i].ops->set(val, ¶ms[i]);
+ mutex_lock(¶m_lock);
+ err = params[i].ops->set(val, ¶ms[i]);
+ mutex_unlock(¶m_lock);
+ return err;
}
}
/* nul-terminate and parse */
save = val[len];
((char *)val)[len] = '\0';
+ BUG_ON(!mutex_is_locked(¶m_lock));
ret = set(val, &kp);
if (ret != 0)
if (i)
buffer[off++] = ',';
p.arg = arr->elem + arr->elemsize * i;
+ BUG_ON(!mutex_is_locked(¶m_lock));
ret = arr->ops->get(buffer + off, &p);
if (ret < 0)
return ret;
if (!attribute->param->ops->get)
return -EPERM;
+ mutex_lock(¶m_lock);
count = attribute->param->ops->get(buf, attribute->param);
+ mutex_unlock(¶m_lock);
if (count > 0) {
strcat(buf, "\n");
++count;
if (!attribute->param->ops->set)
return -EPERM;
+ mutex_lock(¶m_lock);
err = attribute->param->ops->set(buf, attribute->param);
+ mutex_unlock(¶m_lock);
if (!err)
return len;
return err;
#endif
#ifdef CONFIG_SYSFS
+void __kernel_param_lock(void)
+{
+ mutex_lock(¶m_lock);
+}
+EXPORT_SYMBOL(__kernel_param_lock);
+
+void __kernel_param_unlock(void)
+{
+ mutex_unlock(¶m_lock);
+}
+EXPORT_SYMBOL(__kernel_param_unlock);
+
/*
* add_sysfs_param - add a parameter to sysfs
* @mk: struct module_kobject