diff options
author | Sage Weil <sage@inktank.com> | 2013-08-15 14:11:45 -0400 |
---|---|---|
committer | Sage Weil <sage@inktank.com> | 2013-08-15 14:11:45 -0400 |
commit | ee3e542fec6e69bc9fb668698889a37d93950ddf (patch) | |
tree | e74ee766a4764769ef1d3d45d266b4dea64101d3 /fs/sysfs | |
parent | fe2a801b50c0bb8039d627e5ae1fec249d10ff39 (diff) | |
parent | f1d6e17f540af37bb1891480143669ba7636c4cf (diff) |
Merge remote-tracking branch 'linus/master' into testing
Diffstat (limited to 'fs/sysfs')
-rw-r--r-- | fs/sysfs/dir.c | 68 | ||||
-rw-r--r-- | fs/sysfs/file.c | 10 | ||||
-rw-r--r-- | fs/sysfs/group.c | 70 | ||||
-rw-r--r-- | fs/sysfs/inode.c | 2 |
4 files changed, 73 insertions, 77 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index e8e0e71b29d5..e068e744dbdd 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -74,7 +74,7 @@ static int sysfs_sd_compare(const struct sysfs_dirent *left, | |||
74 | } | 74 | } |
75 | 75 | ||
76 | /** | 76 | /** |
77 | * sysfs_link_subling - link sysfs_dirent into sibling rbtree | 77 | * sysfs_link_sibling - link sysfs_dirent into sibling rbtree |
78 | * @sd: sysfs_dirent of interest | 78 | * @sd: sysfs_dirent of interest |
79 | * | 79 | * |
80 | * Link @sd into its sibling rbtree which starts from | 80 | * Link @sd into its sibling rbtree which starts from |
@@ -998,68 +998,38 @@ static struct sysfs_dirent *sysfs_dir_next_pos(const void *ns, | |||
998 | return pos; | 998 | return pos; |
999 | } | 999 | } |
1000 | 1000 | ||
1001 | static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) | 1001 | static int sysfs_readdir(struct file *file, struct dir_context *ctx) |
1002 | { | 1002 | { |
1003 | struct dentry *dentry = filp->f_path.dentry; | 1003 | struct dentry *dentry = file->f_path.dentry; |
1004 | struct sysfs_dirent * parent_sd = dentry->d_fsdata; | 1004 | struct sysfs_dirent * parent_sd = dentry->d_fsdata; |
1005 | struct sysfs_dirent *pos = filp->private_data; | 1005 | struct sysfs_dirent *pos = file->private_data; |
1006 | enum kobj_ns_type type; | 1006 | enum kobj_ns_type type; |
1007 | const void *ns; | 1007 | const void *ns; |
1008 | ino_t ino; | ||
1009 | loff_t off; | ||
1010 | 1008 | ||
1011 | type = sysfs_ns_type(parent_sd); | 1009 | type = sysfs_ns_type(parent_sd); |
1012 | ns = sysfs_info(dentry->d_sb)->ns[type]; | 1010 | ns = sysfs_info(dentry->d_sb)->ns[type]; |
1013 | 1011 | ||
1014 | if (filp->f_pos == 0) { | 1012 | if (!dir_emit_dots(file, ctx)) |
1015 | ino = parent_sd->s_ino; | 1013 | return 0; |
1016 | if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) == 0) | ||
1017 | filp->f_pos++; | ||
1018 | else | ||
1019 | return 0; | ||
1020 | } | ||
1021 | if (filp->f_pos == 1) { | ||
1022 | if (parent_sd->s_parent) | ||
1023 | ino = parent_sd->s_parent->s_ino; | ||
1024 | else | ||
1025 | ino = parent_sd->s_ino; | ||
1026 | if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) == 0) | ||
1027 | filp->f_pos++; | ||
1028 | else | ||
1029 | return 0; | ||
1030 | } | ||
1031 | mutex_lock(&sysfs_mutex); | 1014 | mutex_lock(&sysfs_mutex); |
1032 | off = filp->f_pos; | 1015 | for (pos = sysfs_dir_pos(ns, parent_sd, ctx->pos, pos); |
1033 | for (pos = sysfs_dir_pos(ns, parent_sd, filp->f_pos, pos); | ||
1034 | pos; | 1016 | pos; |
1035 | pos = sysfs_dir_next_pos(ns, parent_sd, filp->f_pos, pos)) { | 1017 | pos = sysfs_dir_next_pos(ns, parent_sd, ctx->pos, pos)) { |
1036 | const char * name; | 1018 | const char *name = pos->s_name; |
1037 | unsigned int type; | 1019 | unsigned int type = dt_type(pos); |
1038 | int len, ret; | 1020 | int len = strlen(name); |
1039 | 1021 | ino_t ino = pos->s_ino; | |
1040 | name = pos->s_name; | 1022 | ctx->pos = pos->s_hash; |
1041 | len = strlen(name); | 1023 | file->private_data = sysfs_get(pos); |
1042 | ino = pos->s_ino; | ||
1043 | type = dt_type(pos); | ||
1044 | off = filp->f_pos = pos->s_hash; | ||
1045 | filp->private_data = sysfs_get(pos); | ||
1046 | 1024 | ||
1047 | mutex_unlock(&sysfs_mutex); | 1025 | mutex_unlock(&sysfs_mutex); |
1048 | ret = filldir(dirent, name, len, off, ino, type); | 1026 | if (!dir_emit(ctx, name, len, ino, type)) |
1027 | return 0; | ||
1049 | mutex_lock(&sysfs_mutex); | 1028 | mutex_lock(&sysfs_mutex); |
1050 | if (ret < 0) | ||
1051 | break; | ||
1052 | } | 1029 | } |
1053 | mutex_unlock(&sysfs_mutex); | 1030 | mutex_unlock(&sysfs_mutex); |
1054 | 1031 | file->private_data = NULL; | |
1055 | /* don't reference last entry if its refcount is dropped */ | 1032 | ctx->pos = INT_MAX; |
1056 | if (!pos) { | ||
1057 | filp->private_data = NULL; | ||
1058 | |||
1059 | /* EOF and not changed as 0 or 1 in read/write path */ | ||
1060 | if (off == filp->f_pos && off > 1) | ||
1061 | filp->f_pos = INT_MAX; | ||
1062 | } | ||
1063 | return 0; | 1033 | return 0; |
1064 | } | 1034 | } |
1065 | 1035 | ||
@@ -1077,7 +1047,7 @@ static loff_t sysfs_dir_llseek(struct file *file, loff_t offset, int whence) | |||
1077 | 1047 | ||
1078 | const struct file_operations sysfs_dir_operations = { | 1048 | const struct file_operations sysfs_dir_operations = { |
1079 | .read = generic_read_dir, | 1049 | .read = generic_read_dir, |
1080 | .readdir = sysfs_readdir, | 1050 | .iterate = sysfs_readdir, |
1081 | .release = sysfs_dir_release, | 1051 | .release = sysfs_dir_release, |
1082 | .llseek = sysfs_dir_llseek, | 1052 | .llseek = sysfs_dir_llseek, |
1083 | }; | 1053 | }; |
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 602f56db0442..d2bb7ed8fa74 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -449,10 +449,12 @@ void sysfs_notify_dirent(struct sysfs_dirent *sd) | |||
449 | 449 | ||
450 | spin_lock_irqsave(&sysfs_open_dirent_lock, flags); | 450 | spin_lock_irqsave(&sysfs_open_dirent_lock, flags); |
451 | 451 | ||
452 | od = sd->s_attr.open; | 452 | if (!WARN_ON(sysfs_type(sd) != SYSFS_KOBJ_ATTR)) { |
453 | if (od) { | 453 | od = sd->s_attr.open; |
454 | atomic_inc(&od->event); | 454 | if (od) { |
455 | wake_up_interruptible(&od->poll); | 455 | atomic_inc(&od->event); |
456 | wake_up_interruptible(&od->poll); | ||
457 | } | ||
456 | } | 458 | } |
457 | 459 | ||
458 | spin_unlock_irqrestore(&sysfs_open_dirent_lock, flags); | 460 | spin_unlock_irqrestore(&sysfs_open_dirent_lock, flags); |
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 | } |
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 0ce3ccf7f401..3e2837a633ed 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
@@ -24,8 +24,6 @@ | |||
24 | #include <linux/security.h> | 24 | #include <linux/security.h> |
25 | #include "sysfs.h" | 25 | #include "sysfs.h" |
26 | 26 | ||
27 | extern struct super_block * sysfs_sb; | ||
28 | |||
29 | static const struct address_space_operations sysfs_aops = { | 27 | static const struct address_space_operations sysfs_aops = { |
30 | .readpage = simple_readpage, | 28 | .readpage = simple_readpage, |
31 | .write_begin = simple_write_begin, | 29 | .write_begin = simple_write_begin, |