diff options
Diffstat (limited to 'fs/sysfs/file.c')
-rw-r--r-- | fs/sysfs/file.c | 65 |
1 files changed, 13 insertions, 52 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); |