aboutsummaryrefslogtreecommitdiffstats
path: root/fs/libfs.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2008-02-08 07:20:26 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-08 12:22:34 -0500
commit8b88b0998e35d239e74446cc30f354bdab86df89 (patch)
treec13773b744cf12b1e30ec9336a4acaf21e46c6d9 /fs/libfs.c
parentefae09f3e99fcc1bdead7bc23a508b3bade3f82f (diff)
libfs: allow error return from simple attributes
Sometimes simple attributes might need to return an error, e.g. for acquiring a mutex interruptibly. In fact we have that situation in spufs already which is the original user of the simple attributes. This patch merged the temporarily forked attributes in spufs back into the main ones and allows to return errors. [akpm@linux-foundation.org: build fix] Signed-off-by: Christoph Hellwig <hch@lst.de> Cc: <stefano.brivio@polimi.it> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Greg KH <greg@kroah.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/libfs.c')
-rw-r--r--fs/libfs.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/fs/libfs.c b/fs/libfs.c
index 5523bde96387..2319415ddb5e 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -583,8 +583,8 @@ int simple_transaction_release(struct inode *inode, struct file *file)
583/* Simple attribute files */ 583/* Simple attribute files */
584 584
585struct simple_attr { 585struct simple_attr {
586 u64 (*get)(void *); 586 int (*get)(void *, u64 *);
587 void (*set)(void *, u64); 587 int (*set)(void *, u64);
588 char get_buf[24]; /* enough to store a u64 and "\n\0" */ 588 char get_buf[24]; /* enough to store a u64 and "\n\0" */
589 char set_buf[24]; 589 char set_buf[24];
590 void *data; 590 void *data;
@@ -595,7 +595,7 @@ struct simple_attr {
595/* simple_attr_open is called by an actual attribute open file operation 595/* simple_attr_open is called by an actual attribute open file operation
596 * to set the attribute specific access operations. */ 596 * to set the attribute specific access operations. */
597int simple_attr_open(struct inode *inode, struct file *file, 597int simple_attr_open(struct inode *inode, struct file *file,
598 u64 (*get)(void *), void (*set)(void *, u64), 598 int (*get)(void *, u64 *), int (*set)(void *, u64),
599 const char *fmt) 599 const char *fmt)
600{ 600{
601 struct simple_attr *attr; 601 struct simple_attr *attr;
@@ -635,14 +635,20 @@ ssize_t simple_attr_read(struct file *file, char __user *buf,
635 return -EACCES; 635 return -EACCES;
636 636
637 mutex_lock(&attr->mutex); 637 mutex_lock(&attr->mutex);
638 if (*ppos) /* continued read */ 638 if (*ppos) { /* continued read */
639 size = strlen(attr->get_buf); 639 size = strlen(attr->get_buf);
640 else /* first read */ 640 } else { /* first read */
641 u64 val;
642 ret = attr->get(attr->data, &val);
643 if (ret)
644 goto out;
645
641 size = scnprintf(attr->get_buf, sizeof(attr->get_buf), 646 size = scnprintf(attr->get_buf, sizeof(attr->get_buf),
642 attr->fmt, 647 attr->fmt, (unsigned long long)val);
643 (unsigned long long)attr->get(attr->data)); 648 }
644 649
645 ret = simple_read_from_buffer(buf, len, ppos, attr->get_buf, size); 650 ret = simple_read_from_buffer(buf, len, ppos, attr->get_buf, size);
651out:
646 mutex_unlock(&attr->mutex); 652 mutex_unlock(&attr->mutex);
647 return ret; 653 return ret;
648} 654}
@@ -657,7 +663,6 @@ ssize_t simple_attr_write(struct file *file, const char __user *buf,
657 ssize_t ret; 663 ssize_t ret;
658 664
659 attr = file->private_data; 665 attr = file->private_data;
660
661 if (!attr->set) 666 if (!attr->set)
662 return -EACCES; 667 return -EACCES;
663 668