sysfs: Functions for adding/removing symlinks to/from attribute groups
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 25 Jan 2013 20:51:13 +0000 (21:51 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 25 Jan 2013 20:51:13 +0000 (21:51 +0100)
The most convenient way to expose ACPI power resources lists of a
device is to put symbolic links to sysfs directories representing
those resources into special attribute groups in the device's sysfs
directory.  For this purpose, it is necessary to be able to add
symbolic links to attribute groups.

For this reason, add sysfs helper functions for adding/removing
symbolic links to/from attribute groups, sysfs_add_link_to_group()
and sysfs_remove_link_from_group(), respectively.

This change set includes a build fix from David Rientjes.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/sysfs/group.c
fs/sysfs/symlink.c
fs/sysfs/sysfs.h
include/linux/sysfs.h

index 2df555c66d57d463381042632ae124ad53aecb42..aec3d5c98c94fa1d3d79de15a44dfa2a4a77e329 100644 (file)
@@ -205,6 +205,48 @@ void sysfs_unmerge_group(struct kobject *kobj,
 }
 EXPORT_SYMBOL_GPL(sysfs_unmerge_group);
 
+/**
+ * sysfs_add_link_to_group - add a symlink to an attribute group.
+ * @kobj:      The kobject containing the group.
+ * @group_name:        The name of the group.
+ * @target:    The target kobject of the symlink to create.
+ * @link_name: The name of the symlink to create.
+ */
+int sysfs_add_link_to_group(struct kobject *kobj, const char *group_name,
+                           struct kobject *target, const char *link_name)
+{
+       struct sysfs_dirent *dir_sd;
+       int error = 0;
+
+       dir_sd = sysfs_get_dirent(kobj->sd, NULL, group_name);
+       if (!dir_sd)
+               return -ENOENT;
+
+       error = sysfs_create_link_sd(dir_sd, target, link_name);
+       sysfs_put(dir_sd);
+
+       return error;
+}
+EXPORT_SYMBOL_GPL(sysfs_add_link_to_group);
+
+/**
+ * sysfs_remove_link_from_group - remove a symlink from an attribute group.
+ * @kobj:      The kobject containing the group.
+ * @group_name:        The name of the group.
+ * @link_name: The name of the symlink to remove.
+ */
+void sysfs_remove_link_from_group(struct kobject *kobj, const char *group_name,
+                                 const char *link_name)
+{
+       struct sysfs_dirent *dir_sd;
+
+       dir_sd = sysfs_get_dirent(kobj->sd, NULL, group_name);
+       if (dir_sd) {
+               sysfs_hash_and_remove(dir_sd, NULL, link_name);
+               sysfs_put(dir_sd);
+       }
+}
+EXPORT_SYMBOL_GPL(sysfs_remove_link_from_group);
 
 EXPORT_SYMBOL_GPL(sysfs_create_group);
 EXPORT_SYMBOL_GPL(sysfs_update_group);
index 3c9eb5624f5e195d6e2b06908f3b21396ccc8723..8c940df97a52bd3e836ef34fc4654553ea105c8d 100644 (file)
 
 #include "sysfs.h"
 
-static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target,
-                               const char *name, int warn)
+static int sysfs_do_create_link_sd(struct sysfs_dirent *parent_sd,
+                                  struct kobject *target,
+                                  const char *name, int warn)
 {
-       struct sysfs_dirent *parent_sd = NULL;
        struct sysfs_dirent *target_sd = NULL;
        struct sysfs_dirent *sd = NULL;
        struct sysfs_addrm_cxt acxt;
        enum kobj_ns_type ns_type;
        int error;
 
-       BUG_ON(!name);
-
-       if (!kobj)
-               parent_sd = &sysfs_root;
-       else
-               parent_sd = kobj->sd;
-
-       error = -EFAULT;
-       if (!parent_sd)
-               goto out_put;
+       BUG_ON(!name || !parent_sd);
 
        /* target->sd can go away beneath us but is protected with
         * sysfs_assoc_lock.  Fetch target_sd from it.
@@ -95,6 +86,34 @@ static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target,
        return error;
 }
 
+/**
+ *     sysfs_create_link_sd - create symlink to a given object.
+ *     @sd:            directory we're creating the link in.
+ *     @target:        object we're pointing to.
+ *     @name:          name of the symlink.
+ */
+int sysfs_create_link_sd(struct sysfs_dirent *sd, struct kobject *target,
+                        const char *name)
+{
+       return sysfs_do_create_link_sd(sd, target, name, 1);
+}
+
+static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target,
+                               const char *name, int warn)
+{
+       struct sysfs_dirent *parent_sd = NULL;
+
+       if (!kobj)
+               parent_sd = &sysfs_root;
+       else
+               parent_sd = kobj->sd;
+
+       if (!parent_sd)
+               return -EFAULT;
+
+       return sysfs_do_create_link_sd(parent_sd, target, name, warn);
+}
+
 /**
  *     sysfs_create_link - create symlink between two objects.
  *     @kobj:  object whose directory we're creating the link in.
index d73c0932bbd6f688b811784236fc1a78ffce3c37..d1e4043eb0c3ab2962bb1b1154b9dc4b20050305 100644 (file)
@@ -240,3 +240,5 @@ void unmap_bin_file(struct sysfs_dirent *attr_sd);
  * symlink.c
  */
 extern const struct inode_operations sysfs_symlink_inode_operations;
+int sysfs_create_link_sd(struct sysfs_dirent *sd, struct kobject *target,
+                        const char *name);
index 381f06db2fe508bd660dd6c10c247aa5aedb5dda..e2cee22f578a6b24d7eb39c1ad298f15115bcb2d 100644 (file)
@@ -181,6 +181,10 @@ int sysfs_merge_group(struct kobject *kobj,
                       const struct attribute_group *grp);
 void sysfs_unmerge_group(struct kobject *kobj,
                       const struct attribute_group *grp);
+int sysfs_add_link_to_group(struct kobject *kobj, const char *group_name,
+                           struct kobject *target, const char *link_name);
+void sysfs_remove_link_from_group(struct kobject *kobj, const char *group_name,
+                                 const char *link_name);
 
 void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr);
 void sysfs_notify_dirent(struct sysfs_dirent *sd);
@@ -326,6 +330,18 @@ static inline void sysfs_unmerge_group(struct kobject *kobj,
 {
 }
 
+static inline int sysfs_add_link_to_group(struct kobject *kobj,
+               const char *group_name, struct kobject *target,
+               const char *link_name)
+{
+       return 0;
+}
+
+static inline void sysfs_remove_link_from_group(struct kobject *kobj,
+               const char *group_name, const char *link_name)
+{
+}
+
 static inline void sysfs_notify(struct kobject *kobj, const char *dir,
                                const char *attr)
 {