summaryrefslogtreecommitdiffstats
path: root/fs/libfs.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2008-02-08 13:20:26 +0100
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-08 18:22:34 +0100
commit8b88b0998e35d239e74446cc30f354bdab86df89 (patch)
treec13773b744cf12b1e30ec9336a4acaf21e46c6d9 /fs/libfs.c
parentNuke duplicate header from sysctl.c (diff)
downloadlinux-8b88b0998e35d239e74446cc30f354bdab86df89.tar.xz
linux-8b88b0998e35d239e74446cc30f354bdab86df89.zip
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)
/* Simple attribute files */
struct simple_attr {
- u64 (*get)(void *);
- void (*set)(void *, u64);
+ int (*get)(void *, u64 *);
+ int (*set)(void *, u64);
char get_buf[24]; /* enough to store a u64 and "\n\0" */
char set_buf[24];
void *data;
@@ -595,7 +595,7 @@ struct simple_attr {
/* simple_attr_open is called by an actual attribute open file operation
* to set the attribute specific access operations. */
int simple_attr_open(struct inode *inode, struct file *file,
- u64 (*get)(void *), void (*set)(void *, u64),
+ int (*get)(void *, u64 *), int (*set)(void *, u64),
const char *fmt)
{
struct simple_attr *attr;
@@ -635,14 +635,20 @@ ssize_t simple_attr_read(struct file *file, char __user *buf,
return -EACCES;
mutex_lock(&attr->mutex);
- if (*ppos) /* continued read */
+ if (*ppos) { /* continued read */
size = strlen(attr->get_buf);
- else /* first read */
+ } else { /* first read */
+ u64 val;
+ ret = attr->get(attr->data, &val);
+ if (ret)
+ goto out;
+
size = scnprintf(attr->get_buf, sizeof(attr->get_buf),
- attr->fmt,
- (unsigned long long)attr->get(attr->data));
+ attr->fmt, (unsigned long long)val);
+ }
ret = simple_read_from_buffer(buf, len, ppos, attr->get_buf, size);
+out:
mutex_unlock(&attr->mutex);
return ret;
}
@@ -657,7 +663,6 @@ ssize_t simple_attr_write(struct file *file, const char __user *buf,
ssize_t ret;
attr = file->private_data;
-
if (!attr->set)
return -EACCES;