diff options
author | Jens Axboe <jens.axboe@oracle.com> | 2010-05-21 15:27:26 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2010-05-21 15:27:26 -0400 |
commit | ee9a3607fb03e804ddf624544105f4e34260c380 (patch) | |
tree | ce41b6e0fa10982a306f6c142a92dbf3c9961284 /fs/sysfs/mount.c | |
parent | b492e95be0ae672922f4734acf3f5d35c30be948 (diff) | |
parent | d515e86e639890b33a09390d062b0831664f04a2 (diff) |
Merge branch 'master' into for-2.6.35
Conflicts:
fs/ext3/fsync.c
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'fs/sysfs/mount.c')
-rw-r--r-- | fs/sysfs/mount.c | 95 |
1 files changed, 92 insertions, 3 deletions
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 776137828dca..281c0c9bc39f 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c | |||
@@ -35,7 +35,7 @@ static const struct super_operations sysfs_ops = { | |||
35 | struct sysfs_dirent sysfs_root = { | 35 | struct sysfs_dirent sysfs_root = { |
36 | .s_name = "", | 36 | .s_name = "", |
37 | .s_count = ATOMIC_INIT(1), | 37 | .s_count = ATOMIC_INIT(1), |
38 | .s_flags = SYSFS_DIR, | 38 | .s_flags = SYSFS_DIR | (KOBJ_NS_TYPE_NONE << SYSFS_NS_TYPE_SHIFT), |
39 | .s_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, | 39 | .s_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, |
40 | .s_ino = 1, | 40 | .s_ino = 1, |
41 | }; | 41 | }; |
@@ -72,18 +72,107 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent) | |||
72 | return 0; | 72 | return 0; |
73 | } | 73 | } |
74 | 74 | ||
75 | static int sysfs_test_super(struct super_block *sb, void *data) | ||
76 | { | ||
77 | struct sysfs_super_info *sb_info = sysfs_info(sb); | ||
78 | struct sysfs_super_info *info = data; | ||
79 | enum kobj_ns_type type; | ||
80 | int found = 1; | ||
81 | |||
82 | for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++) { | ||
83 | if (sb_info->ns[type] != info->ns[type]) | ||
84 | found = 0; | ||
85 | } | ||
86 | return found; | ||
87 | } | ||
88 | |||
89 | static int sysfs_set_super(struct super_block *sb, void *data) | ||
90 | { | ||
91 | int error; | ||
92 | error = set_anon_super(sb, data); | ||
93 | if (!error) | ||
94 | sb->s_fs_info = data; | ||
95 | return error; | ||
96 | } | ||
97 | |||
75 | static int sysfs_get_sb(struct file_system_type *fs_type, | 98 | static int sysfs_get_sb(struct file_system_type *fs_type, |
76 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) | 99 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
77 | { | 100 | { |
78 | return get_sb_single(fs_type, flags, data, sysfs_fill_super, mnt); | 101 | struct sysfs_super_info *info; |
102 | enum kobj_ns_type type; | ||
103 | struct super_block *sb; | ||
104 | int error; | ||
105 | |||
106 | error = -ENOMEM; | ||
107 | info = kzalloc(sizeof(*info), GFP_KERNEL); | ||
108 | if (!info) | ||
109 | goto out; | ||
110 | |||
111 | for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++) | ||
112 | info->ns[type] = kobj_ns_current(type); | ||
113 | |||
114 | sb = sget(fs_type, sysfs_test_super, sysfs_set_super, info); | ||
115 | if (IS_ERR(sb) || sb->s_fs_info != info) | ||
116 | kfree(info); | ||
117 | if (IS_ERR(sb)) { | ||
118 | error = PTR_ERR(sb); | ||
119 | goto out; | ||
120 | } | ||
121 | if (!sb->s_root) { | ||
122 | sb->s_flags = flags; | ||
123 | error = sysfs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0); | ||
124 | if (error) { | ||
125 | deactivate_locked_super(sb); | ||
126 | goto out; | ||
127 | } | ||
128 | sb->s_flags |= MS_ACTIVE; | ||
129 | } | ||
130 | |||
131 | simple_set_mnt(mnt, sb); | ||
132 | error = 0; | ||
133 | out: | ||
134 | return error; | ||
135 | } | ||
136 | |||
137 | static void sysfs_kill_sb(struct super_block *sb) | ||
138 | { | ||
139 | struct sysfs_super_info *info = sysfs_info(sb); | ||
140 | |||
141 | /* Remove the superblock from fs_supers/s_instances | ||
142 | * so we can't find it, before freeing sysfs_super_info. | ||
143 | */ | ||
144 | kill_anon_super(sb); | ||
145 | kfree(info); | ||
79 | } | 146 | } |
80 | 147 | ||
81 | static struct file_system_type sysfs_fs_type = { | 148 | static struct file_system_type sysfs_fs_type = { |
82 | .name = "sysfs", | 149 | .name = "sysfs", |
83 | .get_sb = sysfs_get_sb, | 150 | .get_sb = sysfs_get_sb, |
84 | .kill_sb = kill_anon_super, | 151 | .kill_sb = sysfs_kill_sb, |
85 | }; | 152 | }; |
86 | 153 | ||
154 | void sysfs_exit_ns(enum kobj_ns_type type, const void *ns) | ||
155 | { | ||
156 | struct super_block *sb; | ||
157 | |||
158 | mutex_lock(&sysfs_mutex); | ||
159 | spin_lock(&sb_lock); | ||
160 | list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) { | ||
161 | struct sysfs_super_info *info = sysfs_info(sb); | ||
162 | /* | ||
163 | * If we see a superblock on the fs_supers/s_instances | ||
164 | * list the unmount has not completed and sb->s_fs_info | ||
165 | * points to a valid struct sysfs_super_info. | ||
166 | */ | ||
167 | /* Ignore superblocks with the wrong ns */ | ||
168 | if (info->ns[type] != ns) | ||
169 | continue; | ||
170 | info->ns[type] = NULL; | ||
171 | } | ||
172 | spin_unlock(&sb_lock); | ||
173 | mutex_unlock(&sysfs_mutex); | ||
174 | } | ||
175 | |||
87 | int __init sysfs_init(void) | 176 | int __init sysfs_init(void) |
88 | { | 177 | { |
89 | int err = -ENOMEM; | 178 | int err = -ENOMEM; |