Merge remote-tracking branch 'chrome-platform/for-next'
authorStephen Rothwell <sfr@canb.auug.org.au>
Thu, 5 Nov 2015 03:22:28 +0000 (14:22 +1100)
committerStephen Rothwell <sfr@canb.auug.org.au>
Thu, 5 Nov 2015 03:22:28 +0000 (14:22 +1100)
1  2 
fs/sysfs/group.c
include/linux/sysfs.h

diff --combined fs/sysfs/group.c
@@@ -73,13 -73,26 +73,26 @@@ static int create_files(struct kernfs_n
        }
  
        if (grp->bin_attrs) {
-               for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++) {
+               for (i = 0, bin_attr = grp->bin_attrs; *bin_attr; i++, bin_attr++) {
+                       umode_t mode = (*bin_attr)->attr.mode;
                        if (update)
                                kernfs_remove_by_name(parent,
                                                (*bin_attr)->attr.name);
+                       if (grp->is_bin_visible) {
+                               mode = grp->is_bin_visible(kobj, *bin_attr, i);
+                               if (!mode)
+                                       continue;
+                       }
+                       WARN(mode & ~(SYSFS_PREALLOC | 0664),
+                            "Attribute %s: Invalid permissions 0%o\n",
+                            (*bin_attr)->attr.name, mode);
+                       mode &= SYSFS_PREALLOC | 0664;
                        error = sysfs_add_file_mode_ns(parent,
                                        &(*bin_attr)->attr, true,
-                                       (*bin_attr)->attr.mode, NULL);
+                                       mode, NULL);
                        if (error)
                                break;
                }
@@@ -352,47 -365,3 +365,47 @@@ void sysfs_remove_link_from_group(struc
        }
  }
  EXPORT_SYMBOL_GPL(sysfs_remove_link_from_group);
 +
 +/**
 + * __compat_only_sysfs_link_entry_to_kobj - add a symlink to a kobject pointing
 + * to a group or an attribute
 + * @kobj:             The kobject containing the group.
 + * @target_kobj:      The target kobject.
 + * @target_name:      The name of the target group or attribute.
 + */
 +int __compat_only_sysfs_link_entry_to_kobj(struct kobject *kobj,
 +                                    struct kobject *target_kobj,
 +                                    const char *target_name)
 +{
 +      struct kernfs_node *target;
 +      struct kernfs_node *entry;
 +      struct kernfs_node *link;
 +
 +      /*
 +       * We don't own @target_kobj and it may be removed at any time.
 +       * Synchronize using sysfs_symlink_target_lock. See sysfs_remove_dir()
 +       * for details.
 +       */
 +      spin_lock(&sysfs_symlink_target_lock);
 +      target = target_kobj->sd;
 +      if (target)
 +              kernfs_get(target);
 +      spin_unlock(&sysfs_symlink_target_lock);
 +      if (!target)
 +              return -ENOENT;
 +
 +      entry = kernfs_find_and_get(target_kobj->sd, target_name);
 +      if (!entry) {
 +              kernfs_put(target);
 +              return -ENOENT;
 +      }
 +
 +      link = kernfs_create_link(kobj->sd, target_name, entry);
 +      if (IS_ERR(link) && PTR_ERR(link) == -EEXIST)
 +              sysfs_warn_dup(kobj->sd, target_name);
 +
 +      kernfs_put(entry);
 +      kernfs_put(target);
 +      return IS_ERR(link) ? PTR_ERR(link) : 0;
 +}
 +EXPORT_SYMBOL_GPL(__compat_only_sysfs_link_entry_to_kobj);
diff --combined include/linux/sysfs.h
@@@ -64,10 -64,18 +64,18 @@@ do {                                                       
   *            a new subdirectory with this name.
   * @is_visible:       Optional: Function to return permissions associated with an
   *            attribute of the group. Will be called repeatedly for each
-  *            attribute in the group. Only read/write permissions as well as
-  *            SYSFS_PREALLOC are accepted. Must return 0 if an attribute is
-  *            not visible. The returned value will replace static permissions
-  *            defined in struct attribute or struct bin_attribute.
+  *            non-binary attribute in the group. Only read/write
+  *            permissions as well as SYSFS_PREALLOC are accepted. Must
+  *            return 0 if an attribute is not visible. The returned value
+  *            will replace static permissions defined in struct attribute.
+  * @is_bin_visible:
+  *            Optional: Function to return permissions associated with a
+  *            binary attribute of the group. Will be called repeatedly
+  *            for each binary attribute in the group. Only read/write
+  *            permissions as well as SYSFS_PREALLOC are accepted. Must
+  *            return 0 if a binary attribute is not visible. The returned
+  *            value will replace static permissions defined in
+  *            struct bin_attribute.
   * @attrs:    Pointer to NULL terminated list of attributes.
   * @bin_attrs:        Pointer to NULL terminated list of binary attributes.
   *            Either attrs or bin_attrs or both must be provided.
@@@ -76,6 -84,8 +84,8 @@@ struct attribute_group 
        const char              *name;
        umode_t                 (*is_visible)(struct kobject *,
                                              struct attribute *, int);
+       umode_t                 (*is_bin_visible)(struct kobject *,
+                                                 struct bin_attribute *, int);
        struct attribute        **attrs;
        struct bin_attribute    **bin_attrs;
  };
@@@ -268,9 -278,6 +278,9 @@@ int sysfs_add_link_to_group(struct kobj
                            struct kobject *target, const char *link_name);
  void sysfs_remove_link_from_group(struct kobject *kobj, const char *group_name,
                                  const char *link_name);
 +int __compat_only_sysfs_link_entry_to_kobj(struct kobject *kobj,
 +                                    struct kobject *target_kobj,
 +                                    const char *target_name);
  
  void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr);
  
@@@ -454,14 -461,6 +464,14 @@@ static inline void sysfs_remove_link_fr
  {
  }
  
 +static inline int __compat_only_sysfs_link_entry_to_kobj(
 +      struct kobject *kobj,
 +      struct kobject *target_kobj,
 +      const char *target_name)
 +{
 +      return 0;
 +}
 +
  static inline void sysfs_notify(struct kobject *kobj, const char *dir,
                                const char *attr)
  {