diff options
Diffstat (limited to 'fs/libfs.c')
-rw-r--r-- | fs/libfs.c | 35 |
1 files changed, 23 insertions, 12 deletions
diff --git a/fs/libfs.c b/fs/libfs.c index 5523bde96387..b004dfadd891 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 | ||
585 | struct simple_attr { | 585 | struct 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. */ |
597 | int simple_attr_open(struct inode *inode, struct file *file, | 597 | int 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; |
@@ -615,7 +615,7 @@ int simple_attr_open(struct inode *inode, struct file *file, | |||
615 | return nonseekable_open(inode, file); | 615 | return nonseekable_open(inode, file); |
616 | } | 616 | } |
617 | 617 | ||
618 | int simple_attr_close(struct inode *inode, struct file *file) | 618 | int simple_attr_release(struct inode *inode, struct file *file) |
619 | { | 619 | { |
620 | kfree(file->private_data); | 620 | kfree(file->private_data); |
621 | return 0; | 621 | return 0; |
@@ -634,15 +634,24 @@ ssize_t simple_attr_read(struct file *file, char __user *buf, | |||
634 | if (!attr->get) | 634 | if (!attr->get) |
635 | return -EACCES; | 635 | return -EACCES; |
636 | 636 | ||
637 | mutex_lock(&attr->mutex); | 637 | ret = mutex_lock_interruptible(&attr->mutex); |
638 | if (*ppos) /* continued read */ | 638 | if (ret) |
639 | return ret; | ||
640 | |||
641 | if (*ppos) { /* continued read */ | ||
639 | size = strlen(attr->get_buf); | 642 | size = strlen(attr->get_buf); |
640 | else /* first read */ | 643 | } else { /* first read */ |
644 | u64 val; | ||
645 | ret = attr->get(attr->data, &val); | ||
646 | if (ret) | ||
647 | goto out; | ||
648 | |||
641 | size = scnprintf(attr->get_buf, sizeof(attr->get_buf), | 649 | size = scnprintf(attr->get_buf, sizeof(attr->get_buf), |
642 | attr->fmt, | 650 | attr->fmt, (unsigned long long)val); |
643 | (unsigned long long)attr->get(attr->data)); | 651 | } |
644 | 652 | ||
645 | ret = simple_read_from_buffer(buf, len, ppos, attr->get_buf, size); | 653 | ret = simple_read_from_buffer(buf, len, ppos, attr->get_buf, size); |
654 | out: | ||
646 | mutex_unlock(&attr->mutex); | 655 | mutex_unlock(&attr->mutex); |
647 | return ret; | 656 | return ret; |
648 | } | 657 | } |
@@ -657,11 +666,13 @@ ssize_t simple_attr_write(struct file *file, const char __user *buf, | |||
657 | ssize_t ret; | 666 | ssize_t ret; |
658 | 667 | ||
659 | attr = file->private_data; | 668 | attr = file->private_data; |
660 | |||
661 | if (!attr->set) | 669 | if (!attr->set) |
662 | return -EACCES; | 670 | return -EACCES; |
663 | 671 | ||
664 | mutex_lock(&attr->mutex); | 672 | ret = mutex_lock_interruptible(&attr->mutex); |
673 | if (ret) | ||
674 | return ret; | ||
675 | |||
665 | ret = -EFAULT; | 676 | ret = -EFAULT; |
666 | size = min(sizeof(attr->set_buf) - 1, len); | 677 | size = min(sizeof(attr->set_buf) - 1, len); |
667 | if (copy_from_user(attr->set_buf, buf, size)) | 678 | if (copy_from_user(attr->set_buf, buf, size)) |
@@ -793,6 +804,6 @@ EXPORT_SYMBOL(simple_transaction_get); | |||
793 | EXPORT_SYMBOL(simple_transaction_read); | 804 | EXPORT_SYMBOL(simple_transaction_read); |
794 | EXPORT_SYMBOL(simple_transaction_release); | 805 | EXPORT_SYMBOL(simple_transaction_release); |
795 | EXPORT_SYMBOL_GPL(simple_attr_open); | 806 | EXPORT_SYMBOL_GPL(simple_attr_open); |
796 | EXPORT_SYMBOL_GPL(simple_attr_close); | 807 | EXPORT_SYMBOL_GPL(simple_attr_release); |
797 | EXPORT_SYMBOL_GPL(simple_attr_read); | 808 | EXPORT_SYMBOL_GPL(simple_attr_read); |
798 | EXPORT_SYMBOL_GPL(simple_attr_write); | 809 | EXPORT_SYMBOL_GPL(simple_attr_write); |