diff options
-rw-r--r-- | fs/sysfs/group.c | 17 | ||||
-rw-r--r-- | include/linux/sysfs.h | 18 |
2 files changed, 29 insertions, 6 deletions
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index 39a019936768..51b56e6d9537 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c | |||
@@ -73,13 +73,26 @@ static int create_files(struct kernfs_node *parent, struct kobject *kobj, | |||
73 | } | 73 | } |
74 | 74 | ||
75 | if (grp->bin_attrs) { | 75 | if (grp->bin_attrs) { |
76 | for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++) { | 76 | for (i = 0, bin_attr = grp->bin_attrs; *bin_attr; i++, bin_attr++) { |
77 | umode_t mode = (*bin_attr)->attr.mode; | ||
78 | |||
77 | if (update) | 79 | if (update) |
78 | kernfs_remove_by_name(parent, | 80 | kernfs_remove_by_name(parent, |
79 | (*bin_attr)->attr.name); | 81 | (*bin_attr)->attr.name); |
82 | if (grp->is_bin_visible) { | ||
83 | mode = grp->is_bin_visible(kobj, *bin_attr, i); | ||
84 | if (!mode) | ||
85 | continue; | ||
86 | } | ||
87 | |||
88 | WARN(mode & ~(SYSFS_PREALLOC | 0664), | ||
89 | "Attribute %s: Invalid permissions 0%o\n", | ||
90 | (*bin_attr)->attr.name, mode); | ||
91 | |||
92 | mode &= SYSFS_PREALLOC | 0664; | ||
80 | error = sysfs_add_file_mode_ns(parent, | 93 | error = sysfs_add_file_mode_ns(parent, |
81 | &(*bin_attr)->attr, true, | 94 | &(*bin_attr)->attr, true, |
82 | (*bin_attr)->attr.mode, NULL); | 95 | mode, NULL); |
83 | if (error) | 96 | if (error) |
84 | break; | 97 | break; |
85 | } | 98 | } |
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 9f65758311a4..2f66050d073b 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h | |||
@@ -64,10 +64,18 @@ do { \ | |||
64 | * a new subdirectory with this name. | 64 | * a new subdirectory with this name. |
65 | * @is_visible: Optional: Function to return permissions associated with an | 65 | * @is_visible: Optional: Function to return permissions associated with an |
66 | * attribute of the group. Will be called repeatedly for each | 66 | * attribute of the group. Will be called repeatedly for each |
67 | * attribute in the group. Only read/write permissions as well as | 67 | * non-binary attribute in the group. Only read/write |
68 | * SYSFS_PREALLOC are accepted. Must return 0 if an attribute is | 68 | * permissions as well as SYSFS_PREALLOC are accepted. Must |
69 | * not visible. The returned value will replace static permissions | 69 | * return 0 if an attribute is not visible. The returned value |
70 | * defined in struct attribute or struct bin_attribute. | 70 | * will replace static permissions defined in struct attribute. |
71 | * @is_bin_visible: | ||
72 | * Optional: Function to return permissions associated with a | ||
73 | * binary attribute of the group. Will be called repeatedly | ||
74 | * for each binary attribute in the group. Only read/write | ||
75 | * permissions as well as SYSFS_PREALLOC are accepted. Must | ||
76 | * return 0 if a binary attribute is not visible. The returned | ||
77 | * value will replace static permissions defined in | ||
78 | * struct bin_attribute. | ||
71 | * @attrs: Pointer to NULL terminated list of attributes. | 79 | * @attrs: Pointer to NULL terminated list of attributes. |
72 | * @bin_attrs: Pointer to NULL terminated list of binary attributes. | 80 | * @bin_attrs: Pointer to NULL terminated list of binary attributes. |
73 | * Either attrs or bin_attrs or both must be provided. | 81 | * Either attrs or bin_attrs or both must be provided. |
@@ -76,6 +84,8 @@ struct attribute_group { | |||
76 | const char *name; | 84 | const char *name; |
77 | umode_t (*is_visible)(struct kobject *, | 85 | umode_t (*is_visible)(struct kobject *, |
78 | struct attribute *, int); | 86 | struct attribute *, int); |
87 | umode_t (*is_bin_visible)(struct kobject *, | ||
88 | struct bin_attribute *, int); | ||
79 | struct attribute **attrs; | 89 | struct attribute **attrs; |
80 | struct bin_attribute **bin_attrs; | 90 | struct bin_attribute **bin_attrs; |
81 | }; | 91 | }; |