aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/sysfs/file.c65
-rw-r--r--fs/sysfs/inode.c25
-rw-r--r--fs/sysfs/mount.c8
-rw-r--r--fs/sysfs/sysfs.h16
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/** 53struct 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;
59static inline void 59 int needs_read_fill;
60add_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
69static inline void
70remove_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;
258out:
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
194static 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)
216void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent) 198void 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;
19struct super_block * sysfs_sb = NULL; 19struct super_block * sysfs_sb = NULL;
20struct kmem_cache *sysfs_dir_cachep; 20struct kmem_cache *sysfs_dir_cachep;
21 21
22static void sysfs_clear_inode(struct inode *inode);
23
24static const struct super_operations sysfs_ops = { 22static 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
30static struct sysfs_dirent sysfs_root = { 27static 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
39static void sysfs_clear_inode(struct inode *inode)
40{
41 kfree(inode->i_private);
42}
43
44static int sysfs_fill_super(struct super_block *sb, void *data, int silent) 36static 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;
88extern const struct inode_operations sysfs_dir_inode_operations; 88extern const struct inode_operations sysfs_dir_inode_operations;
89extern const struct inode_operations sysfs_symlink_inode_operations; 89extern const struct inode_operations sysfs_symlink_inode_operations;
90 90
91struct 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
103struct sysfs_buffer_collection {
104 struct list_head associates;
105};
106
107static inline struct sysfs_dirent * sysfs_get(struct sysfs_dirent * sd) 91static inline struct sysfs_dirent * sysfs_get(struct sysfs_dirent * sd)
108{ 92{
109 if (sd) { 93 if (sd) {