Driver core: accept all valid action-strings in uevent-trigger
Kay Sievers [Sun, 8 Jul 2007 20:29:26 +0000 (22:29 +0200)]
This allows the uevent file to handle any type of uevent action to be
triggered by userspace instead of just the "add" uevent.

Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

drivers/base/core.c
include/linux/kobject.h
lib/kobject_uevent.c

index 0455aa7..91a0367 100644 (file)
@@ -24,6 +24,8 @@
 #include "base.h"
 #include "power/power.h"
 
+extern const char *kobject_actions[];
+
 int (*platform_notify)(struct device * dev) = NULL;
 int (*platform_notify_remove)(struct device * dev) = NULL;
 
@@ -303,10 +305,25 @@ out:
 static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
                            const char *buf, size_t count)
 {
-       if (memcmp(buf, "add", 3) != 0)
-               dev_err(dev, "uevent: unsupported action-string; this will "
-                       "be ignored in a future kernel version");
+       size_t len = count;
+       enum kobject_action action;
+
+       if (len && buf[len-1] == '\n')
+               len--;
+
+       for (action = 0; action < KOBJ_MAX; action++) {
+               if (strncmp(kobject_actions[action], buf, len) != 0)
+                       continue;
+               if (kobject_actions[action][len] != '\0')
+                       continue;
+               kobject_uevent(&dev->kobj, action);
+               goto out;
+       }
+
+       dev_err(dev, "uevent: unsupported action-string; this will "
+                    "be ignored in a future kernel version\n");
        kobject_uevent(&dev->kobj, KOBJ_ADD);
+out:
        return count;
 }
 
index 06cbf41..aa2fe22 100644 (file)
@@ -36,15 +36,24 @@ extern char uevent_helper[];
 /* counter to tag the uevent, read only except for the kobject core */
 extern u64 uevent_seqnum;
 
-/* the actions here must match the proper string in lib/kobject_uevent.c */
-typedef int __bitwise kobject_action_t;
+/*
+ * The actions here must match the index to the string array
+ * in lib/kobject_uevent.c
+ *
+ * Do not add new actions here without checking with the driver-core
+ * maintainers. Action strings are not meant to express subsystem
+ * or device specific properties. In most cases you want to send a
+ * kobject_uevent_env(kobj, KOBJ_CHANGE, env) with additional event
+ * specific variables added to the event environment.
+ */
 enum kobject_action {
-       KOBJ_ADD        = (__force kobject_action_t) 0x01,      /* exclusive to core */
-       KOBJ_REMOVE     = (__force kobject_action_t) 0x02,      /* exclusive to core */
-       KOBJ_CHANGE     = (__force kobject_action_t) 0x03,      /* device state change */
-       KOBJ_OFFLINE    = (__force kobject_action_t) 0x04,      /* device offline */
-       KOBJ_ONLINE     = (__force kobject_action_t) 0x05,      /* device online */
-       KOBJ_MOVE       = (__force kobject_action_t) 0x06,      /* device move */
+       KOBJ_ADD,
+       KOBJ_REMOVE,
+       KOBJ_CHANGE,
+       KOBJ_MOVE,
+       KOBJ_ONLINE,
+       KOBJ_OFFLINE,
+       KOBJ_MAX
 };
 
 struct kobject {
index bd5ecbb..6a80c78 100644 (file)
@@ -33,25 +33,15 @@ static DEFINE_SPINLOCK(sequence_lock);
 static struct sock *uevent_sock;
 #endif
 
-static char *action_to_string(enum kobject_action action)
-{
-       switch (action) {
-       case KOBJ_ADD:
-               return "add";
-       case KOBJ_REMOVE:
-               return "remove";
-       case KOBJ_CHANGE:
-               return "change";
-       case KOBJ_OFFLINE:
-               return "offline";
-       case KOBJ_ONLINE:
-               return "online";
-       case KOBJ_MOVE:
-               return "move";
-       default:
-               return NULL;
-       }
-}
+/* the strings here must match the enum in include/linux/kobject.h */
+const char *kobject_actions[] = {
+       "add",
+       "remove",
+       "change",
+       "move",
+       "online",
+       "offline",
+};
 
 /**
  * kobject_uevent_env - send an uevent with environmental data
@@ -83,7 +73,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
 
        pr_debug("%s\n", __FUNCTION__);
 
-       action_string = action_to_string(action);
+       action_string = kobject_actions[action];
        if (!action_string) {
                pr_debug("kobject attempted to send uevent without action_string!\n");
                return -EINVAL;