aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ide/ide-tape.c49
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
2649static void idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t *stage, const char __user *buf, int n) 2649static 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
2676static void idetape_copy_stage_to_user (idetape_tape_t *tape, char __user *buf, idetape_stage_t *stage, int n) 2679static 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
2705static void idetape_init_merge_stage (idetape_tape_t *tape) 2711static 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
3775static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf, 3786static 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
3866static int idetape_write_filemark (ide_drive_t *drive) 3883static int idetape_write_filemark (ide_drive_t *drive)