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/sysfs | |
| 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/sysfs')
| -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 310430baf57..d673d9b5d33 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 7b9a8f132d5..d9ccc830b73 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 8f6d8b1b211..37ff9ffc55f 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 d998e8e2784..8b09e9d882c 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) { |
