diff options
Diffstat (limited to 'fs/sysfs')
| -rw-r--r-- | fs/sysfs/group.c | 70 |
1 files changed, 48 insertions, 22 deletions
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index aec3d5c98c94..09a1a25cd145 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c | |||
| @@ -20,38 +20,64 @@ static void remove_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, | |||
| 20 | const struct attribute_group *grp) | 20 | const struct attribute_group *grp) |
| 21 | { | 21 | { |
| 22 | struct attribute *const* attr; | 22 | struct attribute *const* attr; |
| 23 | int i; | 23 | struct bin_attribute *const* bin_attr; |
| 24 | 24 | ||
| 25 | for (i = 0, attr = grp->attrs; *attr; i++, attr++) | 25 | if (grp->attrs) |
| 26 | sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name); | 26 | for (attr = grp->attrs; *attr; attr++) |
| 27 | sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name); | ||
| 28 | if (grp->bin_attrs) | ||
| 29 | for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++) | ||
| 30 | sysfs_remove_bin_file(kobj, *bin_attr); | ||
| 27 | } | 31 | } |
| 28 | 32 | ||
| 29 | static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, | 33 | static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, |
| 30 | const struct attribute_group *grp, int update) | 34 | const struct attribute_group *grp, int update) |
| 31 | { | 35 | { |
| 32 | struct attribute *const* attr; | 36 | struct attribute *const* attr; |
| 37 | struct bin_attribute *const* bin_attr; | ||
| 33 | int error = 0, i; | 38 | int error = 0, i; |
| 34 | 39 | ||
| 35 | for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++) { | 40 | if (grp->attrs) { |
| 36 | umode_t mode = 0; | 41 | for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++) { |
| 42 | umode_t mode = 0; | ||
| 43 | |||
| 44 | /* | ||
| 45 | * In update mode, we're changing the permissions or | ||
| 46 | * visibility. Do this by first removing then | ||
| 47 | * re-adding (if required) the file. | ||
| 48 | */ | ||
| 49 | if (update) | ||
| 50 | sysfs_hash_and_remove(dir_sd, NULL, | ||
| 51 | (*attr)->name); | ||
| 52 | if (grp->is_visible) { | ||
| 53 | mode = grp->is_visible(kobj, *attr, i); | ||
| 54 | if (!mode) | ||
| 55 | continue; | ||
| 56 | } | ||
| 57 | error = sysfs_add_file_mode(dir_sd, *attr, | ||
| 58 | SYSFS_KOBJ_ATTR, | ||
| 59 | (*attr)->mode | mode); | ||
| 60 | if (unlikely(error)) | ||
| 61 | break; | ||
| 62 | } | ||
| 63 | if (error) { | ||
| 64 | remove_files(dir_sd, kobj, grp); | ||
| 65 | goto exit; | ||
| 66 | } | ||
| 67 | } | ||
| 37 | 68 | ||
| 38 | /* in update mode, we're changing the permissions or | 69 | if (grp->bin_attrs) { |
| 39 | * visibility. Do this by first removing then | 70 | for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++) { |
| 40 | * re-adding (if required) the file */ | 71 | if (update) |
| 41 | if (update) | 72 | sysfs_remove_bin_file(kobj, *bin_attr); |
| 42 | sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name); | 73 | error = sysfs_create_bin_file(kobj, *bin_attr); |
| 43 | if (grp->is_visible) { | 74 | if (error) |
| 44 | mode = grp->is_visible(kobj, *attr, i); | 75 | break; |
| 45 | if (!mode) | ||
| 46 | continue; | ||
| 47 | } | 76 | } |
| 48 | error = sysfs_add_file_mode(dir_sd, *attr, SYSFS_KOBJ_ATTR, | 77 | if (error) |
| 49 | (*attr)->mode | mode); | 78 | remove_files(dir_sd, kobj, grp); |
| 50 | if (unlikely(error)) | ||
| 51 | break; | ||
| 52 | } | 79 | } |
| 53 | if (error) | 80 | exit: |
| 54 | remove_files(dir_sd, kobj, grp); | ||
| 55 | return error; | 81 | return error; |
| 56 | } | 82 | } |
| 57 | 83 | ||
| @@ -67,8 +93,8 @@ static int internal_create_group(struct kobject *kobj, int update, | |||
| 67 | /* Updates may happen before the object has been instantiated */ | 93 | /* Updates may happen before the object has been instantiated */ |
| 68 | if (unlikely(update && !kobj->sd)) | 94 | if (unlikely(update && !kobj->sd)) |
| 69 | return -EINVAL; | 95 | return -EINVAL; |
| 70 | if (!grp->attrs) { | 96 | if (!grp->attrs && !grp->bin_attrs) { |
| 71 | WARN(1, "sysfs: attrs not set by subsystem for group: %s/%s\n", | 97 | WARN(1, "sysfs: (bin_)attrs not set by subsystem for group: %s/%s\n", |
| 72 | kobj->name, grp->name ? "" : grp->name); | 98 | kobj->name, grp->name ? "" : grp->name); |
| 73 | return -EINVAL; | 99 | return -EINVAL; |
| 74 | } | 100 | } |
