aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/sysfs/file.c')
-rw-r--r--fs/sysfs/file.c130
1 files changed, 76 insertions, 54 deletions
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 04f6b0ebc889..310430baf572 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -87,8 +87,8 @@ remove_from_collection(struct sysfs_buffer *buffer, struct inode *node)
87 */ 87 */
88static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer) 88static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer)
89{ 89{
90 struct sysfs_dirent * sd = dentry->d_fsdata; 90 struct sysfs_dirent *attr_sd = dentry->d_fsdata;
91 struct kobject * kobj = to_kobj(dentry->d_parent); 91 struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
92 struct sysfs_ops * ops = buffer->ops; 92 struct sysfs_ops * ops = buffer->ops;
93 int ret = 0; 93 int ret = 0;
94 ssize_t count; 94 ssize_t count;
@@ -98,8 +98,15 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer
98 if (!buffer->page) 98 if (!buffer->page)
99 return -ENOMEM; 99 return -ENOMEM;
100 100
101 buffer->event = atomic_read(&sd->s_event); 101 /* need attr_sd for attr and ops, its parent for kobj */
102 count = ops->show(kobj, sd->s_elem.attr.attr, buffer->page); 102 if (!sysfs_get_active_two(attr_sd))
103 return -ENODEV;
104
105 buffer->event = atomic_read(&attr_sd->s_event);
106 count = ops->show(kobj, attr_sd->s_elem.attr.attr, buffer->page);
107
108 sysfs_put_active_two(attr_sd);
109
103 BUG_ON(count > (ssize_t)PAGE_SIZE); 110 BUG_ON(count > (ssize_t)PAGE_SIZE);
104 if (count >= 0) { 111 if (count >= 0) {
105 buffer->needs_read_fill = 0; 112 buffer->needs_read_fill = 0;
@@ -195,14 +202,23 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t
195 * passing the buffer that we acquired in fill_write_buffer(). 202 * passing the buffer that we acquired in fill_write_buffer().
196 */ 203 */
197 204
198static int 205static int
199flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count) 206flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count)
200{ 207{
201 struct sysfs_dirent *attr_sd = dentry->d_fsdata; 208 struct sysfs_dirent *attr_sd = dentry->d_fsdata;
202 struct kobject * kobj = to_kobj(dentry->d_parent); 209 struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
203 struct sysfs_ops * ops = buffer->ops; 210 struct sysfs_ops * ops = buffer->ops;
211 int rc;
212
213 /* need attr_sd for attr and ops, its parent for kobj */
214 if (!sysfs_get_active_two(attr_sd))
215 return -ENODEV;
216
217 rc = ops->store(kobj, attr_sd->s_elem.attr.attr, buffer->page, count);
218
219 sysfs_put_active_two(attr_sd);
204 220
205 return ops->store(kobj, attr_sd->s_elem.attr.attr, buffer->page, count); 221 return rc;
206} 222}
207 223
208 224
@@ -246,22 +262,22 @@ out:
246 262
247static int sysfs_open_file(struct inode *inode, struct file *file) 263static int sysfs_open_file(struct inode *inode, struct file *file)
248{ 264{
249 struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent);
250 struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; 265 struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
251 struct attribute *attr = attr_sd->s_elem.attr.attr; 266 struct attribute *attr = attr_sd->s_elem.attr.attr;
267 struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
252 struct sysfs_buffer_collection *set; 268 struct sysfs_buffer_collection *set;
253 struct sysfs_buffer * buffer; 269 struct sysfs_buffer * buffer;
254 struct sysfs_ops * ops = NULL; 270 struct sysfs_ops * ops = NULL;
255 int error = 0; 271 int error;
256 272
257 if (!kobj || !attr) 273 /* need attr_sd for attr and ops, its parent for kobj */
258 goto Einval; 274 if (!sysfs_get_active_two(attr_sd))
275 return -ENODEV;
259 276
260 /* Grab the module reference for this attribute if we have one */ 277 /* Grab the module reference for this attribute */
261 if (!try_module_get(attr->owner)) { 278 error = -ENODEV;
262 error = -ENODEV; 279 if (!try_module_get(attr->owner))
263 goto Done; 280 goto err_sput;
264 }
265 281
266 /* if the kobject has no ktype, then we assume that it is a subsystem 282 /* if the kobject has no ktype, then we assume that it is a subsystem
267 * itself, and use ops for it. 283 * itself, and use ops for it.
@@ -276,30 +292,30 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
276 /* No sysfs operations, either from having no subsystem, 292 /* No sysfs operations, either from having no subsystem,
277 * or the subsystem have no operations. 293 * or the subsystem have no operations.
278 */ 294 */
295 error = -EACCES;
279 if (!ops) 296 if (!ops)
280 goto Eaccess; 297 goto err_mput;
281 298
282 /* make sure we have a collection to add our buffers to */ 299 /* make sure we have a collection to add our buffers to */
283 mutex_lock(&inode->i_mutex); 300 mutex_lock(&inode->i_mutex);
284 if (!(set = inode->i_private)) { 301 if (!(set = inode->i_private)) {
285 if (!(set = inode->i_private = kmalloc(sizeof(struct sysfs_buffer_collection), GFP_KERNEL))) { 302 error = -ENOMEM;
286 error = -ENOMEM; 303 if (!(set = inode->i_private = kmalloc(sizeof(struct sysfs_buffer_collection), GFP_KERNEL)))
287 goto Done; 304 goto err_mput;
288 } else { 305 else
289 INIT_LIST_HEAD(&set->associates); 306 INIT_LIST_HEAD(&set->associates);
290 }
291 } 307 }
292 mutex_unlock(&inode->i_mutex); 308 mutex_unlock(&inode->i_mutex);
293 309
310 error = -EACCES;
311
294 /* File needs write support. 312 /* File needs write support.
295 * The inode's perms must say it's ok, 313 * The inode's perms must say it's ok,
296 * and we must have a store method. 314 * and we must have a store method.
297 */ 315 */
298 if (file->f_mode & FMODE_WRITE) { 316 if (file->f_mode & FMODE_WRITE) {
299
300 if (!(inode->i_mode & S_IWUGO) || !ops->store) 317 if (!(inode->i_mode & S_IWUGO) || !ops->store)
301 goto Eaccess; 318 goto err_mput;
302
303 } 319 }
304 320
305 /* File needs read support. 321 /* File needs read support.
@@ -308,46 +324,45 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
308 */ 324 */
309 if (file->f_mode & FMODE_READ) { 325 if (file->f_mode & FMODE_READ) {
310 if (!(inode->i_mode & S_IRUGO) || !ops->show) 326 if (!(inode->i_mode & S_IRUGO) || !ops->show)
311 goto Eaccess; 327 goto err_mput;
312 } 328 }
313 329
314 /* No error? Great, allocate a buffer for the file, and store it 330 /* No error? Great, allocate a buffer for the file, and store it
315 * it in file->private_data for easy access. 331 * it in file->private_data for easy access.
316 */ 332 */
333 error = -ENOMEM;
317 buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL); 334 buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL);
318 if (buffer) { 335 if (!buffer)
319 INIT_LIST_HEAD(&buffer->associates); 336 goto err_mput;
320 init_MUTEX(&buffer->sem);
321 buffer->needs_read_fill = 1;
322 buffer->ops = ops;
323 add_to_collection(buffer, inode);
324 file->private_data = buffer;
325 } else
326 error = -ENOMEM;
327 goto Done;
328 337
329 Einval: 338 INIT_LIST_HEAD(&buffer->associates);
330 error = -EINVAL; 339 init_MUTEX(&buffer->sem);
331 goto Done; 340 buffer->needs_read_fill = 1;
332 Eaccess: 341 buffer->ops = ops;
333 error = -EACCES; 342 add_to_collection(buffer, inode);
343 file->private_data = buffer;
344
345 /* open succeeded, put active references and pin attr_sd */
346 sysfs_put_active_two(attr_sd);
347 sysfs_get(attr_sd);
348 return 0;
349
350 err_mput:
334 module_put(attr->owner); 351 module_put(attr->owner);
335 Done: 352 err_sput:
336 if (error) 353 sysfs_put_active_two(attr_sd);
337 kobject_put(kobj);
338 return error; 354 return error;
339} 355}
340 356
341static int sysfs_release(struct inode * inode, struct file * filp) 357static int sysfs_release(struct inode * inode, struct file * filp)
342{ 358{
343 struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent);
344 struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata; 359 struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata;
345 struct attribute *attr = attr_sd->s_elem.attr.attr; 360 struct attribute *attr = attr_sd->s_elem.attr.attr;
346 struct sysfs_buffer * buffer = filp->private_data; 361 struct sysfs_buffer * buffer = filp->private_data;
347 362
348 if (buffer) 363 if (buffer)
349 remove_from_collection(buffer, inode); 364 remove_from_collection(buffer, inode);
350 kobject_put(kobj); 365 sysfs_put(attr_sd);
351 /* After this point, attr should not be accessed. */ 366 /* After this point, attr should not be accessed. */
352 module_put(attr->owner); 367 module_put(attr->owner);
353 368
@@ -376,18 +391,25 @@ static int sysfs_release(struct inode * inode, struct file * filp)
376static unsigned int sysfs_poll(struct file *filp, poll_table *wait) 391static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
377{ 392{
378 struct sysfs_buffer * buffer = filp->private_data; 393 struct sysfs_buffer * buffer = filp->private_data;
379 struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent); 394 struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata;
380 struct sysfs_dirent * sd = filp->f_path.dentry->d_fsdata; 395 struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
381 int res = 0; 396
397 /* need parent for the kobj, grab both */
398 if (!sysfs_get_active_two(attr_sd))
399 goto trigger;
382 400
383 poll_wait(filp, &kobj->poll, wait); 401 poll_wait(filp, &kobj->poll, wait);
384 402
385 if (buffer->event != atomic_read(&sd->s_event)) { 403 sysfs_put_active_two(attr_sd);
386 res = POLLERR|POLLPRI;
387 buffer->needs_read_fill = 1;
388 }
389 404
390 return res; 405 if (buffer->event != atomic_read(&attr_sd->s_event))
406 goto trigger;
407
408 return 0;
409
410 trigger:
411 buffer->needs_read_fill = 1;
412 return POLLERR|POLLPRI;
391} 413}
392 414
393 415