diff options
Diffstat (limited to 'fs/libfs.c')
-rw-r--r-- | fs/libfs.c | 46 |
1 files changed, 27 insertions, 19 deletions
diff --git a/fs/libfs.c b/fs/libfs.c index 6e68b700958d..b004dfadd891 100644 --- a/fs/libfs.c +++ b/fs/libfs.c | |||
@@ -341,13 +341,10 @@ int simple_prepare_write(struct file *file, struct page *page, | |||
341 | unsigned from, unsigned to) | 341 | unsigned from, unsigned to) |
342 | { | 342 | { |
343 | if (!PageUptodate(page)) { | 343 | if (!PageUptodate(page)) { |
344 | if (to - from != PAGE_CACHE_SIZE) { | 344 | if (to - from != PAGE_CACHE_SIZE) |
345 | void *kaddr = kmap_atomic(page, KM_USER0); | 345 | zero_user_segments(page, |
346 | memset(kaddr, 0, from); | 346 | 0, from, |
347 | memset(kaddr + to, 0, PAGE_CACHE_SIZE - to); | 347 | to, PAGE_CACHE_SIZE); |
348 | flush_dcache_page(page); | ||
349 | kunmap_atomic(kaddr, KM_USER0); | ||
350 | } | ||
351 | } | 348 | } |
352 | return 0; | 349 | return 0; |
353 | } | 350 | } |
@@ -586,8 +583,8 @@ int simple_transaction_release(struct inode *inode, struct file *file) | |||
586 | /* Simple attribute files */ | 583 | /* Simple attribute files */ |
587 | 584 | ||
588 | struct simple_attr { | 585 | struct simple_attr { |
589 | u64 (*get)(void *); | 586 | int (*get)(void *, u64 *); |
590 | void (*set)(void *, u64); | 587 | int (*set)(void *, u64); |
591 | 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" */ |
592 | char set_buf[24]; | 589 | char set_buf[24]; |
593 | void *data; | 590 | void *data; |
@@ -598,7 +595,7 @@ struct simple_attr { | |||
598 | /* 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 |
599 | * to set the attribute specific access operations. */ | 596 | * to set the attribute specific access operations. */ |
600 | int simple_attr_open(struct inode *inode, struct file *file, | 597 | int simple_attr_open(struct inode *inode, struct file *file, |
601 | u64 (*get)(void *), void (*set)(void *, u64), | 598 | int (*get)(void *, u64 *), int (*set)(void *, u64), |
602 | const char *fmt) | 599 | const char *fmt) |
603 | { | 600 | { |
604 | struct simple_attr *attr; | 601 | struct simple_attr *attr; |
@@ -618,7 +615,7 @@ int simple_attr_open(struct inode *inode, struct file *file, | |||
618 | return nonseekable_open(inode, file); | 615 | return nonseekable_open(inode, file); |
619 | } | 616 | } |
620 | 617 | ||
621 | int simple_attr_close(struct inode *inode, struct file *file) | 618 | int simple_attr_release(struct inode *inode, struct file *file) |
622 | { | 619 | { |
623 | kfree(file->private_data); | 620 | kfree(file->private_data); |
624 | return 0; | 621 | return 0; |
@@ -637,15 +634,24 @@ ssize_t simple_attr_read(struct file *file, char __user *buf, | |||
637 | if (!attr->get) | 634 | if (!attr->get) |
638 | return -EACCES; | 635 | return -EACCES; |
639 | 636 | ||
640 | mutex_lock(&attr->mutex); | 637 | ret = mutex_lock_interruptible(&attr->mutex); |
641 | if (*ppos) /* continued read */ | 638 | if (ret) |
639 | return ret; | ||
640 | |||
641 | if (*ppos) { /* continued read */ | ||
642 | size = strlen(attr->get_buf); | 642 | size = strlen(attr->get_buf); |
643 | else /* first read */ | 643 | } else { /* first read */ |
644 | u64 val; | ||
645 | ret = attr->get(attr->data, &val); | ||
646 | if (ret) | ||
647 | goto out; | ||
648 | |||
644 | size = scnprintf(attr->get_buf, sizeof(attr->get_buf), | 649 | size = scnprintf(attr->get_buf, sizeof(attr->get_buf), |
645 | attr->fmt, | 650 | attr->fmt, (unsigned long long)val); |
646 | (unsigned long long)attr->get(attr->data)); | 651 | } |
647 | 652 | ||
648 | 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: | ||
649 | mutex_unlock(&attr->mutex); | 655 | mutex_unlock(&attr->mutex); |
650 | return ret; | 656 | return ret; |
651 | } | 657 | } |
@@ -660,11 +666,13 @@ ssize_t simple_attr_write(struct file *file, const char __user *buf, | |||
660 | ssize_t ret; | 666 | ssize_t ret; |
661 | 667 | ||
662 | attr = file->private_data; | 668 | attr = file->private_data; |
663 | |||
664 | if (!attr->set) | 669 | if (!attr->set) |
665 | return -EACCES; | 670 | return -EACCES; |
666 | 671 | ||
667 | mutex_lock(&attr->mutex); | 672 | ret = mutex_lock_interruptible(&attr->mutex); |
673 | if (ret) | ||
674 | return ret; | ||
675 | |||
668 | ret = -EFAULT; | 676 | ret = -EFAULT; |
669 | size = min(sizeof(attr->set_buf) - 1, len); | 677 | size = min(sizeof(attr->set_buf) - 1, len); |
670 | if (copy_from_user(attr->set_buf, buf, size)) | 678 | if (copy_from_user(attr->set_buf, buf, size)) |
@@ -796,6 +804,6 @@ EXPORT_SYMBOL(simple_transaction_get); | |||
796 | EXPORT_SYMBOL(simple_transaction_read); | 804 | EXPORT_SYMBOL(simple_transaction_read); |
797 | EXPORT_SYMBOL(simple_transaction_release); | 805 | EXPORT_SYMBOL(simple_transaction_release); |
798 | EXPORT_SYMBOL_GPL(simple_attr_open); | 806 | EXPORT_SYMBOL_GPL(simple_attr_open); |
799 | EXPORT_SYMBOL_GPL(simple_attr_close); | 807 | EXPORT_SYMBOL_GPL(simple_attr_release); |
800 | EXPORT_SYMBOL_GPL(simple_attr_read); | 808 | EXPORT_SYMBOL_GPL(simple_attr_read); |
801 | EXPORT_SYMBOL_GPL(simple_attr_write); | 809 | EXPORT_SYMBOL_GPL(simple_attr_write); |