diff options
author | Tejun Heo <htejun@gmail.com> | 2007-06-13 14:45:16 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-07-11 19:09:05 -0400 |
commit | 73107cb3ad3963c0f929ae681c05081eafb1c079 (patch) | |
tree | 78c9647d5e6a0d9c89cb8c37b7533aad8f805302 /fs | |
parent | 0ab66088c855eca68513bdd7442a426c4b374ced (diff) |
sysfs: kill attribute file orphaning
Now that sysfs_dirent can be disconnected from kobject on deletion,
there is no need to orphan each attribute files. All [bin_]attribute
nodes are automatically orphaned when the parent node is deleted.
Kill attribute file orphaning.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/sysfs/file.c | 65 | ||||
-rw-r--r-- | fs/sysfs/inode.c | 25 | ||||
-rw-r--r-- | fs/sysfs/mount.c | 8 | ||||
-rw-r--r-- | fs/sysfs/sysfs.h | 16 |
4 files changed, 13 insertions, 101 deletions
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 310430baf572..d673d9b5d33f 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -50,29 +50,15 @@ static struct sysfs_ops subsys_sysfs_ops = { | |||
50 | .store = subsys_attr_store, | 50 | .store = subsys_attr_store, |
51 | }; | 51 | }; |
52 | 52 | ||
53 | /** | 53 | struct sysfs_buffer { |
54 | * add_to_collection - add buffer to a collection | 54 | size_t count; |
55 | * @buffer: buffer to be added | 55 | loff_t pos; |
56 | * @node: inode of set to add to | 56 | char * page; |
57 | */ | 57 | struct sysfs_ops * ops; |
58 | 58 | struct semaphore sem; | |
59 | static inline void | 59 | int needs_read_fill; |
60 | add_to_collection(struct sysfs_buffer *buffer, struct inode *node) | 60 | int event; |
61 | { | 61 | }; |
62 | struct sysfs_buffer_collection *set = node->i_private; | ||
63 | |||
64 | mutex_lock(&node->i_mutex); | ||
65 | list_add(&buffer->associates, &set->associates); | ||
66 | mutex_unlock(&node->i_mutex); | ||
67 | } | ||
68 | |||
69 | static inline void | ||
70 | remove_from_collection(struct sysfs_buffer *buffer, struct inode *node) | ||
71 | { | ||
72 | mutex_lock(&node->i_mutex); | ||
73 | list_del(&buffer->associates); | ||
74 | mutex_unlock(&node->i_mutex); | ||
75 | } | ||
76 | 62 | ||
77 | /** | 63 | /** |
78 | * fill_read_buffer - allocate and fill buffer from object. | 64 | * fill_read_buffer - allocate and fill buffer from object. |
@@ -144,10 +130,7 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
144 | 130 | ||
145 | down(&buffer->sem); | 131 | down(&buffer->sem); |
146 | if (buffer->needs_read_fill) { | 132 | if (buffer->needs_read_fill) { |
147 | if (buffer->orphaned) | 133 | retval = fill_read_buffer(file->f_path.dentry,buffer); |
148 | retval = -ENODEV; | ||
149 | else | ||
150 | retval = fill_read_buffer(file->f_path.dentry,buffer); | ||
151 | if (retval) | 134 | if (retval) |
152 | goto out; | 135 | goto out; |
153 | } | 136 | } |
@@ -246,16 +229,11 @@ sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t | |||
246 | ssize_t len; | 229 | ssize_t len; |
247 | 230 | ||
248 | down(&buffer->sem); | 231 | down(&buffer->sem); |
249 | if (buffer->orphaned) { | ||
250 | len = -ENODEV; | ||
251 | goto out; | ||
252 | } | ||
253 | len = fill_write_buffer(buffer, buf, count); | 232 | len = fill_write_buffer(buffer, buf, count); |
254 | if (len > 0) | 233 | if (len > 0) |
255 | len = flush_write_buffer(file->f_path.dentry, buffer, len); | 234 | len = flush_write_buffer(file->f_path.dentry, buffer, len); |
256 | if (len > 0) | 235 | if (len > 0) |
257 | *ppos += len; | 236 | *ppos += len; |
258 | out: | ||
259 | up(&buffer->sem); | 237 | up(&buffer->sem); |
260 | return len; | 238 | return len; |
261 | } | 239 | } |
@@ -265,7 +243,6 @@ static int sysfs_open_file(struct inode *inode, struct file *file) | |||
265 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; | 243 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; |
266 | struct attribute *attr = attr_sd->s_elem.attr.attr; | 244 | struct attribute *attr = attr_sd->s_elem.attr.attr; |
267 | struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj; | 245 | struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj; |
268 | struct sysfs_buffer_collection *set; | ||
269 | struct sysfs_buffer * buffer; | 246 | struct sysfs_buffer * buffer; |
270 | struct sysfs_ops * ops = NULL; | 247 | struct sysfs_ops * ops = NULL; |
271 | int error; | 248 | int error; |
@@ -289,26 +266,14 @@ static int sysfs_open_file(struct inode *inode, struct file *file) | |||
289 | else | 266 | else |
290 | ops = &subsys_sysfs_ops; | 267 | ops = &subsys_sysfs_ops; |
291 | 268 | ||
269 | error = -EACCES; | ||
270 | |||
292 | /* No sysfs operations, either from having no subsystem, | 271 | /* No sysfs operations, either from having no subsystem, |
293 | * or the subsystem have no operations. | 272 | * or the subsystem have no operations. |
294 | */ | 273 | */ |
295 | error = -EACCES; | ||
296 | if (!ops) | 274 | if (!ops) |
297 | goto err_mput; | 275 | goto err_mput; |
298 | 276 | ||
299 | /* make sure we have a collection to add our buffers to */ | ||
300 | mutex_lock(&inode->i_mutex); | ||
301 | if (!(set = inode->i_private)) { | ||
302 | error = -ENOMEM; | ||
303 | if (!(set = inode->i_private = kmalloc(sizeof(struct sysfs_buffer_collection), GFP_KERNEL))) | ||
304 | goto err_mput; | ||
305 | else | ||
306 | INIT_LIST_HEAD(&set->associates); | ||
307 | } | ||
308 | mutex_unlock(&inode->i_mutex); | ||
309 | |||
310 | error = -EACCES; | ||
311 | |||
312 | /* File needs write support. | 277 | /* File needs write support. |
313 | * The inode's perms must say it's ok, | 278 | * The inode's perms must say it's ok, |
314 | * and we must have a store method. | 279 | * and we must have a store method. |
@@ -335,11 +300,9 @@ static int sysfs_open_file(struct inode *inode, struct file *file) | |||
335 | if (!buffer) | 300 | if (!buffer) |
336 | goto err_mput; | 301 | goto err_mput; |
337 | 302 | ||
338 | INIT_LIST_HEAD(&buffer->associates); | ||
339 | init_MUTEX(&buffer->sem); | 303 | init_MUTEX(&buffer->sem); |
340 | buffer->needs_read_fill = 1; | 304 | buffer->needs_read_fill = 1; |
341 | buffer->ops = ops; | 305 | buffer->ops = ops; |
342 | add_to_collection(buffer, inode); | ||
343 | file->private_data = buffer; | 306 | file->private_data = buffer; |
344 | 307 | ||
345 | /* open succeeded, put active references and pin attr_sd */ | 308 | /* open succeeded, put active references and pin attr_sd */ |
@@ -358,10 +321,8 @@ static int sysfs_release(struct inode * inode, struct file * filp) | |||
358 | { | 321 | { |
359 | struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata; | 322 | struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata; |
360 | struct attribute *attr = attr_sd->s_elem.attr.attr; | 323 | struct attribute *attr = attr_sd->s_elem.attr.attr; |
361 | struct sysfs_buffer * buffer = filp->private_data; | 324 | struct sysfs_buffer *buffer = filp->private_data; |
362 | 325 | ||
363 | if (buffer) | ||
364 | remove_from_collection(buffer, inode); | ||
365 | sysfs_put(attr_sd); | 326 | sysfs_put(attr_sd); |
366 | /* After this point, attr should not be accessed. */ | 327 | /* After this point, attr should not be accessed. */ |
367 | module_put(attr->owner); | 328 | module_put(attr->owner); |
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 7b9a8f132d5a..d9ccc830b73a 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
@@ -191,24 +191,6 @@ int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *)) | |||
191 | return error; | 191 | return error; |
192 | } | 192 | } |
193 | 193 | ||
194 | static inline void orphan_all_buffers(struct inode *node) | ||
195 | { | ||
196 | struct sysfs_buffer_collection *set; | ||
197 | struct sysfs_buffer *buf; | ||
198 | |||
199 | mutex_lock_nested(&node->i_mutex, I_MUTEX_CHILD); | ||
200 | set = node->i_private; | ||
201 | if (set) { | ||
202 | list_for_each_entry(buf, &set->associates, associates) { | ||
203 | down(&buf->sem); | ||
204 | buf->orphaned = 1; | ||
205 | up(&buf->sem); | ||
206 | } | ||
207 | } | ||
208 | mutex_unlock(&node->i_mutex); | ||
209 | } | ||
210 | |||
211 | |||
212 | /* | 194 | /* |
213 | * Unhashes the dentry corresponding to given sysfs_dirent | 195 | * Unhashes the dentry corresponding to given sysfs_dirent |
214 | * Called with parent inode's i_mutex held. | 196 | * Called with parent inode's i_mutex held. |
@@ -216,7 +198,6 @@ static inline void orphan_all_buffers(struct inode *node) | |||
216 | void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent) | 198 | void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent) |
217 | { | 199 | { |
218 | struct dentry *dentry = NULL; | 200 | struct dentry *dentry = NULL; |
219 | struct inode *inode; | ||
220 | 201 | ||
221 | /* We're not holding a reference to ->s_dentry dentry but the | 202 | /* We're not holding a reference to ->s_dentry dentry but the |
222 | * field will stay valid as long as sysfs_lock is held. | 203 | * field will stay valid as long as sysfs_lock is held. |
@@ -236,17 +217,11 @@ void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent) | |||
236 | spin_lock(&dcache_lock); | 217 | spin_lock(&dcache_lock); |
237 | spin_lock(&dentry->d_lock); | 218 | spin_lock(&dentry->d_lock); |
238 | if (!d_unhashed(dentry) && dentry->d_inode) { | 219 | if (!d_unhashed(dentry) && dentry->d_inode) { |
239 | inode = dentry->d_inode; | ||
240 | spin_lock(&inode->i_lock); | ||
241 | __iget(inode); | ||
242 | spin_unlock(&inode->i_lock); | ||
243 | dget_locked(dentry); | 220 | dget_locked(dentry); |
244 | __d_drop(dentry); | 221 | __d_drop(dentry); |
245 | spin_unlock(&dentry->d_lock); | 222 | spin_unlock(&dentry->d_lock); |
246 | spin_unlock(&dcache_lock); | 223 | spin_unlock(&dcache_lock); |
247 | simple_unlink(parent->d_inode, dentry); | 224 | simple_unlink(parent->d_inode, dentry); |
248 | orphan_all_buffers(inode); | ||
249 | iput(inode); | ||
250 | } else { | 225 | } else { |
251 | spin_unlock(&dentry->d_lock); | 226 | spin_unlock(&dentry->d_lock); |
252 | spin_unlock(&dcache_lock); | 227 | spin_unlock(&dcache_lock); |
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 8f6d8b1b211f..37ff9ffc55f0 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c | |||
@@ -19,12 +19,9 @@ struct vfsmount *sysfs_mount; | |||
19 | struct super_block * sysfs_sb = NULL; | 19 | struct super_block * sysfs_sb = NULL; |
20 | struct kmem_cache *sysfs_dir_cachep; | 20 | struct kmem_cache *sysfs_dir_cachep; |
21 | 21 | ||
22 | static void sysfs_clear_inode(struct inode *inode); | ||
23 | |||
24 | static const struct super_operations sysfs_ops = { | 22 | static const struct super_operations sysfs_ops = { |
25 | .statfs = simple_statfs, | 23 | .statfs = simple_statfs, |
26 | .drop_inode = sysfs_delete_inode, | 24 | .drop_inode = sysfs_delete_inode, |
27 | .clear_inode = sysfs_clear_inode, | ||
28 | }; | 25 | }; |
29 | 26 | ||
30 | static struct sysfs_dirent sysfs_root = { | 27 | static struct sysfs_dirent sysfs_root = { |
@@ -36,11 +33,6 @@ static struct sysfs_dirent sysfs_root = { | |||
36 | .s_ino = 1, | 33 | .s_ino = 1, |
37 | }; | 34 | }; |
38 | 35 | ||
39 | static void sysfs_clear_inode(struct inode *inode) | ||
40 | { | ||
41 | kfree(inode->i_private); | ||
42 | } | ||
43 | |||
44 | static int sysfs_fill_super(struct super_block *sb, void *data, int silent) | 36 | static int sysfs_fill_super(struct super_block *sb, void *data, int silent) |
45 | { | 37 | { |
46 | struct inode *inode; | 38 | struct inode *inode; |
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index d998e8e27841..8b09e9d882c2 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
@@ -88,22 +88,6 @@ extern const struct file_operations bin_fops; | |||
88 | extern const struct inode_operations sysfs_dir_inode_operations; | 88 | extern const struct inode_operations sysfs_dir_inode_operations; |
89 | extern const struct inode_operations sysfs_symlink_inode_operations; | 89 | extern const struct inode_operations sysfs_symlink_inode_operations; |
90 | 90 | ||
91 | struct sysfs_buffer { | ||
92 | struct list_head associates; | ||
93 | size_t count; | ||
94 | loff_t pos; | ||
95 | char * page; | ||
96 | struct sysfs_ops * ops; | ||
97 | struct semaphore sem; | ||
98 | int orphaned; | ||
99 | int needs_read_fill; | ||
100 | int event; | ||
101 | }; | ||
102 | |||
103 | struct sysfs_buffer_collection { | ||
104 | struct list_head associates; | ||
105 | }; | ||
106 | |||
107 | static inline struct sysfs_dirent * sysfs_get(struct sysfs_dirent * sd) | 91 | static inline struct sysfs_dirent * sysfs_get(struct sysfs_dirent * sd) |
108 | { | 92 | { |
109 | if (sd) { | 93 | if (sd) { |