libfs: allow error return from simple attributes
[sfrench/cifs-2.6.git] / fs / libfs.c
index 5523bde963879d6060c9a9d19396e8a8615b40a2..2319415ddb5e966fd99f3851460adfcad55de440 100644 (file)
@@ -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;