diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ide/ide-tape.c | 49 |
1 files changed, 33 insertions, 16 deletions
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index f04791a58df0..09f3a7dab28a 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c | |||
@@ -2646,21 +2646,23 @@ static idetape_stage_t *idetape_kmalloc_stage (idetape_tape_t *tape) | |||
2646 | return __idetape_kmalloc_stage(tape, 0, 0); | 2646 | return __idetape_kmalloc_stage(tape, 0, 0); |
2647 | } | 2647 | } |
2648 | 2648 | ||
2649 | static void idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t *stage, const char __user *buf, int n) | 2649 | static int idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t *stage, const char __user *buf, int n) |
2650 | { | 2650 | { |
2651 | struct idetape_bh *bh = tape->bh; | 2651 | struct idetape_bh *bh = tape->bh; |
2652 | int count; | 2652 | int count; |
2653 | int ret = 0; | ||
2653 | 2654 | ||
2654 | while (n) { | 2655 | while (n) { |
2655 | #if IDETAPE_DEBUG_BUGS | 2656 | #if IDETAPE_DEBUG_BUGS |
2656 | if (bh == NULL) { | 2657 | if (bh == NULL) { |
2657 | printk(KERN_ERR "ide-tape: bh == NULL in " | 2658 | printk(KERN_ERR "ide-tape: bh == NULL in " |
2658 | "idetape_copy_stage_from_user\n"); | 2659 | "idetape_copy_stage_from_user\n"); |
2659 | return; | 2660 | return 1; |
2660 | } | 2661 | } |
2661 | #endif /* IDETAPE_DEBUG_BUGS */ | 2662 | #endif /* IDETAPE_DEBUG_BUGS */ |
2662 | count = min((unsigned int)(bh->b_size - atomic_read(&bh->b_count)), (unsigned int)n); | 2663 | count = min((unsigned int)(bh->b_size - atomic_read(&bh->b_count)), (unsigned int)n); |
2663 | copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf, count); | 2664 | if (copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf, count)) |
2665 | ret = 1; | ||
2664 | n -= count; | 2666 | n -= count; |
2665 | atomic_add(count, &bh->b_count); | 2667 | atomic_add(count, &bh->b_count); |
2666 | buf += count; | 2668 | buf += count; |
@@ -2671,23 +2673,26 @@ static void idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t | |||
2671 | } | 2673 | } |
2672 | } | 2674 | } |
2673 | tape->bh = bh; | 2675 | tape->bh = bh; |
2676 | return ret; | ||
2674 | } | 2677 | } |
2675 | 2678 | ||
2676 | static void idetape_copy_stage_to_user (idetape_tape_t *tape, char __user *buf, idetape_stage_t *stage, int n) | 2679 | static int idetape_copy_stage_to_user (idetape_tape_t *tape, char __user *buf, idetape_stage_t *stage, int n) |
2677 | { | 2680 | { |
2678 | struct idetape_bh *bh = tape->bh; | 2681 | struct idetape_bh *bh = tape->bh; |
2679 | int count; | 2682 | int count; |
2683 | int ret = 0; | ||
2680 | 2684 | ||
2681 | while (n) { | 2685 | while (n) { |
2682 | #if IDETAPE_DEBUG_BUGS | 2686 | #if IDETAPE_DEBUG_BUGS |
2683 | if (bh == NULL) { | 2687 | if (bh == NULL) { |
2684 | printk(KERN_ERR "ide-tape: bh == NULL in " | 2688 | printk(KERN_ERR "ide-tape: bh == NULL in " |
2685 | "idetape_copy_stage_to_user\n"); | 2689 | "idetape_copy_stage_to_user\n"); |
2686 | return; | 2690 | return 1; |
2687 | } | 2691 | } |
2688 | #endif /* IDETAPE_DEBUG_BUGS */ | 2692 | #endif /* IDETAPE_DEBUG_BUGS */ |
2689 | count = min(tape->b_count, n); | 2693 | count = min(tape->b_count, n); |
2690 | copy_to_user(buf, tape->b_data, count); | 2694 | if (copy_to_user(buf, tape->b_data, count)) |
2695 | ret = 1; | ||
2691 | n -= count; | 2696 | n -= count; |
2692 | tape->b_data += count; | 2697 | tape->b_data += count; |
2693 | tape->b_count -= count; | 2698 | tape->b_count -= count; |
@@ -2700,6 +2705,7 @@ static void idetape_copy_stage_to_user (idetape_tape_t *tape, char __user *buf, | |||
2700 | } | 2705 | } |
2701 | } | 2706 | } |
2702 | } | 2707 | } |
2708 | return ret; | ||
2703 | } | 2709 | } |
2704 | 2710 | ||
2705 | static void idetape_init_merge_stage (idetape_tape_t *tape) | 2711 | static void idetape_init_merge_stage (idetape_tape_t *tape) |
@@ -3719,6 +3725,7 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf, | |||
3719 | struct ide_tape_obj *tape = ide_tape_f(file); | 3725 | struct ide_tape_obj *tape = ide_tape_f(file); |
3720 | ide_drive_t *drive = tape->drive; | 3726 | ide_drive_t *drive = tape->drive; |
3721 | ssize_t bytes_read,temp, actually_read = 0, rc; | 3727 | ssize_t bytes_read,temp, actually_read = 0, rc; |
3728 | ssize_t ret = 0; | ||
3722 | 3729 | ||
3723 | #if IDETAPE_DEBUG_LOG | 3730 | #if IDETAPE_DEBUG_LOG |
3724 | if (tape->debug_level >= 3) | 3731 | if (tape->debug_level >= 3) |
@@ -3737,7 +3744,8 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf, | |||
3737 | return (0); | 3744 | return (0); |
3738 | if (tape->merge_stage_size) { | 3745 | if (tape->merge_stage_size) { |
3739 | actually_read = min((unsigned int)(tape->merge_stage_size), (unsigned int)count); | 3746 | actually_read = min((unsigned int)(tape->merge_stage_size), (unsigned int)count); |
3740 | idetape_copy_stage_to_user(tape, buf, tape->merge_stage, actually_read); | 3747 | if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, actually_read)) |
3748 | ret = -EFAULT; | ||
3741 | buf += actually_read; | 3749 | buf += actually_read; |
3742 | tape->merge_stage_size -= actually_read; | 3750 | tape->merge_stage_size -= actually_read; |
3743 | count -= actually_read; | 3751 | count -= actually_read; |
@@ -3746,7 +3754,8 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf, | |||
3746 | bytes_read = idetape_add_chrdev_read_request(drive, tape->capabilities.ctl); | 3754 | bytes_read = idetape_add_chrdev_read_request(drive, tape->capabilities.ctl); |
3747 | if (bytes_read <= 0) | 3755 | if (bytes_read <= 0) |
3748 | goto finish; | 3756 | goto finish; |
3749 | idetape_copy_stage_to_user(tape, buf, tape->merge_stage, bytes_read); | 3757 | if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, bytes_read)) |
3758 | ret = -EFAULT; | ||
3750 | buf += bytes_read; | 3759 | buf += bytes_read; |
3751 | count -= bytes_read; | 3760 | count -= bytes_read; |
3752 | actually_read += bytes_read; | 3761 | actually_read += bytes_read; |
@@ -3756,7 +3765,8 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf, | |||
3756 | if (bytes_read <= 0) | 3765 | if (bytes_read <= 0) |
3757 | goto finish; | 3766 | goto finish; |
3758 | temp = min((unsigned long)count, (unsigned long)bytes_read); | 3767 | temp = min((unsigned long)count, (unsigned long)bytes_read); |
3759 | idetape_copy_stage_to_user(tape, buf, tape->merge_stage, temp); | 3768 | if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, temp)) |
3769 | ret = -EFAULT; | ||
3760 | actually_read += temp; | 3770 | actually_read += temp; |
3761 | tape->merge_stage_size = bytes_read-temp; | 3771 | tape->merge_stage_size = bytes_read-temp; |
3762 | } | 3772 | } |
@@ -3769,7 +3779,8 @@ finish: | |||
3769 | idetape_space_over_filemarks(drive, MTFSF, 1); | 3779 | idetape_space_over_filemarks(drive, MTFSF, 1); |
3770 | return 0; | 3780 | return 0; |
3771 | } | 3781 | } |
3772 | return actually_read; | 3782 | |
3783 | return (ret) ? ret : actually_read; | ||
3773 | } | 3784 | } |
3774 | 3785 | ||
3775 | static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf, | 3786 | static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf, |
@@ -3777,7 +3788,8 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf, | |||
3777 | { | 3788 | { |
3778 | struct ide_tape_obj *tape = ide_tape_f(file); | 3789 | struct ide_tape_obj *tape = ide_tape_f(file); |
3779 | ide_drive_t *drive = tape->drive; | 3790 | ide_drive_t *drive = tape->drive; |
3780 | ssize_t retval, actually_written = 0; | 3791 | ssize_t actually_written = 0; |
3792 | ssize_t ret = 0; | ||
3781 | 3793 | ||
3782 | /* The drive is write protected. */ | 3794 | /* The drive is write protected. */ |
3783 | if (tape->write_prot) | 3795 | if (tape->write_prot) |
@@ -3813,7 +3825,7 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf, | |||
3813 | * some drives (Seagate STT3401A) will return an error. | 3825 | * some drives (Seagate STT3401A) will return an error. |
3814 | */ | 3826 | */ |
3815 | if (drive->dsc_overlap) { | 3827 | if (drive->dsc_overlap) { |
3816 | retval = idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, 0, tape->merge_stage->bh); | 3828 | ssize_t retval = idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, 0, tape->merge_stage->bh); |
3817 | if (retval < 0) { | 3829 | if (retval < 0) { |
3818 | __idetape_kfree_stage(tape->merge_stage); | 3830 | __idetape_kfree_stage(tape->merge_stage); |
3819 | tape->merge_stage = NULL; | 3831 | tape->merge_stage = NULL; |
@@ -3834,12 +3846,14 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf, | |||
3834 | } | 3846 | } |
3835 | #endif /* IDETAPE_DEBUG_BUGS */ | 3847 | #endif /* IDETAPE_DEBUG_BUGS */ |
3836 | actually_written = min((unsigned int)(tape->stage_size - tape->merge_stage_size), (unsigned int)count); | 3848 | actually_written = min((unsigned int)(tape->stage_size - tape->merge_stage_size), (unsigned int)count); |
3837 | idetape_copy_stage_from_user(tape, tape->merge_stage, buf, actually_written); | 3849 | if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, actually_written)) |
3850 | ret = -EFAULT; | ||
3838 | buf += actually_written; | 3851 | buf += actually_written; |
3839 | tape->merge_stage_size += actually_written; | 3852 | tape->merge_stage_size += actually_written; |
3840 | count -= actually_written; | 3853 | count -= actually_written; |
3841 | 3854 | ||
3842 | if (tape->merge_stage_size == tape->stage_size) { | 3855 | if (tape->merge_stage_size == tape->stage_size) { |
3856 | ssize_t retval; | ||
3843 | tape->merge_stage_size = 0; | 3857 | tape->merge_stage_size = 0; |
3844 | retval = idetape_add_chrdev_write_request(drive, tape->capabilities.ctl); | 3858 | retval = idetape_add_chrdev_write_request(drive, tape->capabilities.ctl); |
3845 | if (retval <= 0) | 3859 | if (retval <= 0) |
@@ -3847,7 +3861,9 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf, | |||
3847 | } | 3861 | } |
3848 | } | 3862 | } |
3849 | while (count >= tape->stage_size) { | 3863 | while (count >= tape->stage_size) { |
3850 | idetape_copy_stage_from_user(tape, tape->merge_stage, buf, tape->stage_size); | 3864 | ssize_t retval; |
3865 | if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, tape->stage_size)) | ||
3866 | ret = -EFAULT; | ||
3851 | buf += tape->stage_size; | 3867 | buf += tape->stage_size; |
3852 | count -= tape->stage_size; | 3868 | count -= tape->stage_size; |
3853 | retval = idetape_add_chrdev_write_request(drive, tape->capabilities.ctl); | 3869 | retval = idetape_add_chrdev_write_request(drive, tape->capabilities.ctl); |
@@ -3857,10 +3873,11 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf, | |||
3857 | } | 3873 | } |
3858 | if (count) { | 3874 | if (count) { |
3859 | actually_written += count; | 3875 | actually_written += count; |
3860 | idetape_copy_stage_from_user(tape, tape->merge_stage, buf, count); | 3876 | if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, count)) |
3877 | ret = -EFAULT; | ||
3861 | tape->merge_stage_size += count; | 3878 | tape->merge_stage_size += count; |
3862 | } | 3879 | } |
3863 | return (actually_written); | 3880 | return (ret) ? ret : actually_written; |
3864 | } | 3881 | } |
3865 | 3882 | ||
3866 | static int idetape_write_filemark (ide_drive_t *drive) | 3883 | static int idetape_write_filemark (ide_drive_t *drive) |