diff options
-rw-r--r-- | drivers/ide/ide-tape.c | 305 |
1 files changed, 84 insertions, 221 deletions
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index b373ac876352..d2e9c09b5215 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c | |||
@@ -131,12 +131,6 @@ enum { | |||
131 | IDETAPE_DIR_WRITE = (1 << 2), | 131 | IDETAPE_DIR_WRITE = (1 << 2), |
132 | }; | 132 | }; |
133 | 133 | ||
134 | struct idetape_bh { | ||
135 | u32 b_size; | ||
136 | atomic_t b_count; | ||
137 | char *b_data; | ||
138 | }; | ||
139 | |||
140 | /* Tape door status */ | 134 | /* Tape door status */ |
141 | #define DOOR_UNLOCKED 0 | 135 | #define DOOR_UNLOCKED 0 |
142 | #define DOOR_LOCKED 1 | 136 | #define DOOR_LOCKED 1 |
@@ -218,14 +212,12 @@ typedef struct ide_tape_obj { | |||
218 | 212 | ||
219 | /* Data buffer size chosen based on the tape's recommendation */ | 213 | /* Data buffer size chosen based on the tape's recommendation */ |
220 | int buffer_size; | 214 | int buffer_size; |
221 | /* merge buffer */ | 215 | /* Staging buffer of buffer_size bytes */ |
222 | struct idetape_bh *merge_bh; | 216 | void *buf; |
223 | /* size of the merge buffer */ | 217 | /* The read/write cursor */ |
224 | int merge_bh_size; | 218 | void *cur; |
225 | /* pointer to current buffer head within the merge buffer */ | 219 | /* The number of valid bytes in buf */ |
226 | struct idetape_bh *bh; | 220 | size_t valid; |
227 | char *b_data; | ||
228 | int b_count; | ||
229 | 221 | ||
230 | /* Measures average tape speed */ | 222 | /* Measures average tape speed */ |
231 | unsigned long avg_time; | 223 | unsigned long avg_time; |
@@ -351,15 +343,6 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense) | |||
351 | } | 343 | } |
352 | } | 344 | } |
353 | 345 | ||
354 | /* Free data buffers completely. */ | ||
355 | static void ide_tape_kfree_buffer(idetape_tape_t *tape) | ||
356 | { | ||
357 | struct idetape_bh *bh = tape->merge_bh; | ||
358 | |||
359 | kfree(bh->b_data); | ||
360 | kfree(bh); | ||
361 | } | ||
362 | |||
363 | static void ide_tape_handle_dsc(ide_drive_t *); | 346 | static void ide_tape_handle_dsc(ide_drive_t *); |
364 | 347 | ||
365 | static int ide_tape_callback(ide_drive_t *drive, int dsc) | 348 | static int ide_tape_callback(ide_drive_t *drive, int dsc) |
@@ -603,8 +586,7 @@ static void ide_tape_create_rw_cmd(idetape_tape_t *tape, | |||
603 | struct ide_atapi_pc *pc, struct request *rq, | 586 | struct ide_atapi_pc *pc, struct request *rq, |
604 | u8 opcode) | 587 | u8 opcode) |
605 | { | 588 | { |
606 | struct idetape_bh *bh = (struct idetape_bh *)rq->special; | 589 | unsigned int length = rq->nr_sectors; |
607 | unsigned int length = rq->current_nr_sectors; | ||
608 | 590 | ||
609 | ide_init_pc(pc); | 591 | ide_init_pc(pc); |
610 | put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]); | 592 | put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]); |
@@ -616,14 +598,11 @@ static void ide_tape_create_rw_cmd(idetape_tape_t *tape, | |||
616 | if (pc->req_xfer == tape->buffer_size) | 598 | if (pc->req_xfer == tape->buffer_size) |
617 | pc->flags |= PC_FLAG_DMA_OK; | 599 | pc->flags |= PC_FLAG_DMA_OK; |
618 | 600 | ||
619 | if (opcode == READ_6) { | 601 | if (opcode == READ_6) |
620 | pc->c[0] = READ_6; | 602 | pc->c[0] = READ_6; |
621 | atomic_set(&bh->b_count, 0); | 603 | else if (opcode == WRITE_6) { |
622 | } else if (opcode == WRITE_6) { | ||
623 | pc->c[0] = WRITE_6; | 604 | pc->c[0] = WRITE_6; |
624 | pc->flags |= PC_FLAG_WRITING; | 605 | pc->flags |= PC_FLAG_WRITING; |
625 | pc->b_data = bh->b_data; | ||
626 | pc->b_count = atomic_read(&bh->b_count); | ||
627 | } | 606 | } |
628 | 607 | ||
629 | memcpy(rq->cmd, pc->c, 12); | 608 | memcpy(rq->cmd, pc->c, 12); |
@@ -639,10 +618,8 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, | |||
639 | struct ide_cmd cmd; | 618 | struct ide_cmd cmd; |
640 | u8 stat; | 619 | u8 stat; |
641 | 620 | ||
642 | debug_log(DBG_SENSE, "sector: %llu, nr_sectors: %lu," | 621 | debug_log(DBG_SENSE, "sector: %llu, nr_sectors: %lu\n" |
643 | " current_nr_sectors: %u\n", | 622 | (unsigned long long)rq->sector, rq->nr_sectors); |
644 | (unsigned long long)rq->sector, rq->nr_sectors, | ||
645 | rq->current_nr_sectors); | ||
646 | 623 | ||
647 | if (!(blk_special_request(rq) || blk_sense_request(rq))) { | 624 | if (!(blk_special_request(rq) || blk_sense_request(rq))) { |
648 | /* We do not support buffer cache originated requests. */ | 625 | /* We do not support buffer cache originated requests. */ |
@@ -749,89 +726,6 @@ out: | |||
749 | } | 726 | } |
750 | 727 | ||
751 | /* | 728 | /* |
752 | * It returns a pointer to the newly allocated buffer, or NULL in case | ||
753 | * of failure. | ||
754 | */ | ||
755 | static struct idetape_bh *ide_tape_kmalloc_buffer(idetape_tape_t *tape, | ||
756 | int full) | ||
757 | { | ||
758 | struct idetape_bh *bh; | ||
759 | |||
760 | bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL); | ||
761 | if (!bh) | ||
762 | return NULL; | ||
763 | |||
764 | bh->b_data = kmalloc(tape->buffer_size, GFP_KERNEL); | ||
765 | if (!bh->b_data) { | ||
766 | kfree(bh); | ||
767 | return NULL; | ||
768 | } | ||
769 | |||
770 | bh->b_size = tape->buffer_size; | ||
771 | atomic_set(&bh->b_count, full ? bh->b_size : 0); | ||
772 | |||
773 | return bh; | ||
774 | } | ||
775 | |||
776 | static int idetape_copy_stage_from_user(idetape_tape_t *tape, | ||
777 | const char __user *buf, int n) | ||
778 | { | ||
779 | struct idetape_bh *bh = tape->bh; | ||
780 | int ret = 0; | ||
781 | |||
782 | if (n) { | ||
783 | if (bh == NULL || n > bh->b_size - atomic_read(&bh->b_count)) { | ||
784 | printk(KERN_ERR "ide-tape: bh == NULL in %s\n", | ||
785 | __func__); | ||
786 | return 1; | ||
787 | } | ||
788 | if (copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf, | ||
789 | n)) | ||
790 | ret = 1; | ||
791 | atomic_add(n, &bh->b_count); | ||
792 | if (atomic_read(&bh->b_count) == bh->b_size) | ||
793 | tape->bh = NULL; | ||
794 | } | ||
795 | |||
796 | return ret; | ||
797 | } | ||
798 | |||
799 | static int idetape_copy_stage_to_user(idetape_tape_t *tape, char __user *buf, | ||
800 | int n) | ||
801 | { | ||
802 | struct idetape_bh *bh = tape->bh; | ||
803 | int ret = 0; | ||
804 | |||
805 | if (n) { | ||
806 | if (bh == NULL || n > tape->b_count) { | ||
807 | printk(KERN_ERR "ide-tape: bh == NULL in %s\n", | ||
808 | __func__); | ||
809 | return 1; | ||
810 | } | ||
811 | if (copy_to_user(buf, tape->b_data, n)) | ||
812 | ret = 1; | ||
813 | tape->b_data += n; | ||
814 | tape->b_count -= n; | ||
815 | if (!tape->b_count) | ||
816 | tape->bh = NULL; | ||
817 | } | ||
818 | return ret; | ||
819 | } | ||
820 | |||
821 | static void idetape_init_merge_buffer(idetape_tape_t *tape) | ||
822 | { | ||
823 | struct idetape_bh *bh = tape->merge_bh; | ||
824 | tape->bh = tape->merge_bh; | ||
825 | |||
826 | if (tape->chrdev_dir == IDETAPE_DIR_WRITE) | ||
827 | atomic_set(&bh->b_count, 0); | ||
828 | else { | ||
829 | tape->b_data = bh->b_data; | ||
830 | tape->b_count = atomic_read(&bh->b_count); | ||
831 | } | ||
832 | } | ||
833 | |||
834 | /* | ||
835 | * Write a filemark if write_filemark=1. Flush the device buffers without | 729 | * Write a filemark if write_filemark=1. Flush the device buffers without |
836 | * writing a filemark otherwise. | 730 | * writing a filemark otherwise. |
837 | */ | 731 | */ |
@@ -928,10 +822,10 @@ static void __ide_tape_discard_merge_buffer(ide_drive_t *drive) | |||
928 | return; | 822 | return; |
929 | 823 | ||
930 | clear_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags); | 824 | clear_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags); |
931 | tape->merge_bh_size = 0; | 825 | tape->valid = 0; |
932 | if (tape->merge_bh != NULL) { | 826 | if (tape->buf != NULL) { |
933 | ide_tape_kfree_buffer(tape); | 827 | kfree(tape->buf); |
934 | tape->merge_bh = NULL; | 828 | tape->buf = NULL; |
935 | } | 829 | } |
936 | 830 | ||
937 | tape->chrdev_dir = IDETAPE_DIR_NONE; | 831 | tape->chrdev_dir = IDETAPE_DIR_NONE; |
@@ -985,8 +879,7 @@ static void ide_tape_discard_merge_buffer(ide_drive_t *drive, | |||
985 | * Generate a read/write request for the block device interface and wait for it | 879 | * Generate a read/write request for the block device interface and wait for it |
986 | * to be serviced. | 880 | * to be serviced. |
987 | */ | 881 | */ |
988 | static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks, | 882 | static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks) |
989 | struct idetape_bh *bh) | ||
990 | { | 883 | { |
991 | idetape_tape_t *tape = drive->driver_data; | 884 | idetape_tape_t *tape = drive->driver_data; |
992 | size_t size = blocks * tape->blk_size; | 885 | size_t size = blocks * tape->blk_size; |
@@ -1000,11 +893,10 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks, | |||
1000 | rq->cmd_type = REQ_TYPE_SPECIAL; | 893 | rq->cmd_type = REQ_TYPE_SPECIAL; |
1001 | rq->cmd[13] = cmd; | 894 | rq->cmd[13] = cmd; |
1002 | rq->rq_disk = tape->disk; | 895 | rq->rq_disk = tape->disk; |
1003 | rq->special = (void *)bh; | ||
1004 | rq->sector = tape->first_frame; | 896 | rq->sector = tape->first_frame; |
1005 | 897 | ||
1006 | if (size) { | 898 | if (size) { |
1007 | ret = blk_rq_map_kern(drive->queue, rq, bh->b_data, size, | 899 | ret = blk_rq_map_kern(drive->queue, rq, tape->buf, size, |
1008 | __GFP_WAIT); | 900 | __GFP_WAIT); |
1009 | if (ret) | 901 | if (ret) |
1010 | goto out_put; | 902 | goto out_put; |
@@ -1012,17 +904,17 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks, | |||
1012 | 904 | ||
1013 | blk_execute_rq(drive->queue, tape->disk, rq, 0); | 905 | blk_execute_rq(drive->queue, tape->disk, rq, 0); |
1014 | 906 | ||
1015 | /* calculate the number of transferred bytes and update bh */ | 907 | /* calculate the number of transferred bytes and update buffer state */ |
1016 | size -= rq->data_len; | 908 | size -= rq->data_len; |
909 | tape->cur = tape->buf; | ||
1017 | if (cmd == REQ_IDETAPE_READ) | 910 | if (cmd == REQ_IDETAPE_READ) |
1018 | atomic_add(size, &bh->b_count); | 911 | tape->valid = size; |
912 | else | ||
913 | tape->valid = 0; | ||
1019 | 914 | ||
1020 | ret = size; | 915 | ret = size; |
1021 | if (rq->errors == IDE_DRV_ERROR_GENERAL) | 916 | if (rq->errors == IDE_DRV_ERROR_GENERAL) |
1022 | ret = -EIO; | 917 | ret = -EIO; |
1023 | |||
1024 | if (tape->merge_bh) | ||
1025 | idetape_init_merge_buffer(tape); | ||
1026 | out_put: | 918 | out_put: |
1027 | blk_put_request(rq); | 919 | blk_put_request(rq); |
1028 | return ret; | 920 | return ret; |
@@ -1064,49 +956,33 @@ static void idetape_create_space_cmd(struct ide_atapi_pc *pc, int count, u8 cmd) | |||
1064 | /* Queue up a character device originated write request. */ | 956 | /* Queue up a character device originated write request. */ |
1065 | static int idetape_add_chrdev_write_request(ide_drive_t *drive, int blocks) | 957 | static int idetape_add_chrdev_write_request(ide_drive_t *drive, int blocks) |
1066 | { | 958 | { |
1067 | idetape_tape_t *tape = drive->driver_data; | ||
1068 | |||
1069 | debug_log(DBG_CHRDEV, "Enter %s\n", __func__); | 959 | debug_log(DBG_CHRDEV, "Enter %s\n", __func__); |
1070 | 960 | ||
1071 | return idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, | 961 | return idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, blocks); |
1072 | blocks, tape->merge_bh); | ||
1073 | } | 962 | } |
1074 | 963 | ||
1075 | static void ide_tape_flush_merge_buffer(ide_drive_t *drive) | 964 | static void ide_tape_flush_merge_buffer(ide_drive_t *drive) |
1076 | { | 965 | { |
1077 | idetape_tape_t *tape = drive->driver_data; | 966 | idetape_tape_t *tape = drive->driver_data; |
1078 | int blocks; | 967 | int blocks; |
1079 | struct idetape_bh *bh; | ||
1080 | 968 | ||
1081 | if (tape->chrdev_dir != IDETAPE_DIR_WRITE) { | 969 | if (tape->chrdev_dir != IDETAPE_DIR_WRITE) { |
1082 | printk(KERN_ERR "ide-tape: bug: Trying to empty merge buffer" | 970 | printk(KERN_ERR "ide-tape: bug: Trying to empty merge buffer" |
1083 | " but we are not writing.\n"); | 971 | " but we are not writing.\n"); |
1084 | return; | 972 | return; |
1085 | } | 973 | } |
1086 | if (tape->merge_bh_size > tape->buffer_size) { | 974 | if (tape->buf) { |
1087 | printk(KERN_ERR "ide-tape: bug: merge_buffer too big\n"); | 975 | blocks = tape->valid / tape->blk_size; |
1088 | tape->merge_bh_size = tape->buffer_size; | 976 | if (tape->valid % tape->blk_size) { |
1089 | } | ||
1090 | if (tape->merge_bh_size) { | ||
1091 | blocks = tape->merge_bh_size / tape->blk_size; | ||
1092 | if (tape->merge_bh_size % tape->blk_size) { | ||
1093 | unsigned int i = tape->blk_size - | ||
1094 | tape->merge_bh_size % tape->blk_size; | ||
1095 | blocks++; | 977 | blocks++; |
1096 | bh = tape->bh; | 978 | memset(tape->buf + tape->valid, 0, |
1097 | if (bh) { | 979 | tape->blk_size - tape->valid % tape->blk_size); |
1098 | memset(bh->b_data + atomic_read(&bh->b_count), | ||
1099 | 0, i); | ||
1100 | atomic_add(i, &bh->b_count); | ||
1101 | } else | ||
1102 | printk(KERN_INFO "ide-tape: bug, bh NULL\n"); | ||
1103 | } | 980 | } |
1104 | (void) idetape_add_chrdev_write_request(drive, blocks); | 981 | (void) idetape_add_chrdev_write_request(drive, blocks); |
1105 | tape->merge_bh_size = 0; | ||
1106 | } | 982 | } |
1107 | if (tape->merge_bh != NULL) { | 983 | if (tape->buf != NULL) { |
1108 | ide_tape_kfree_buffer(tape); | 984 | kfree(tape->buf); |
1109 | tape->merge_bh = NULL; | 985 | tape->buf = NULL; |
1110 | } | 986 | } |
1111 | tape->chrdev_dir = IDETAPE_DIR_NONE; | 987 | tape->chrdev_dir = IDETAPE_DIR_NONE; |
1112 | } | 988 | } |
@@ -1122,15 +998,15 @@ static int idetape_init_read(ide_drive_t *drive) | |||
1122 | ide_tape_flush_merge_buffer(drive); | 998 | ide_tape_flush_merge_buffer(drive); |
1123 | idetape_flush_tape_buffers(drive); | 999 | idetape_flush_tape_buffers(drive); |
1124 | } | 1000 | } |
1125 | if (tape->merge_bh || tape->merge_bh_size) { | 1001 | if (tape->buf || tape->valid) { |
1126 | printk(KERN_ERR "ide-tape: merge_bh_size should be" | 1002 | printk(KERN_ERR "ide-tape: valid should be 0 now\n"); |
1127 | " 0 now\n"); | 1003 | tape->valid = 0; |
1128 | tape->merge_bh_size = 0; | ||
1129 | } | 1004 | } |
1130 | tape->merge_bh = ide_tape_kmalloc_buffer(tape, 0); | 1005 | tape->buf = kmalloc(tape->buffer_size, GFP_KERNEL); |
1131 | if (!tape->merge_bh) | 1006 | if (!tape->buf) |
1132 | return -ENOMEM; | 1007 | return -ENOMEM; |
1133 | tape->chrdev_dir = IDETAPE_DIR_READ; | 1008 | tape->chrdev_dir = IDETAPE_DIR_READ; |
1009 | tape->cur = tape->buf; | ||
1134 | 1010 | ||
1135 | /* | 1011 | /* |
1136 | * Issue a read 0 command to ensure that DSC handshake is | 1012 | * Issue a read 0 command to ensure that DSC handshake is |
@@ -1140,11 +1016,10 @@ static int idetape_init_read(ide_drive_t *drive) | |||
1140 | */ | 1016 | */ |
1141 | if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) { | 1017 | if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) { |
1142 | bytes_read = idetape_queue_rw_tail(drive, | 1018 | bytes_read = idetape_queue_rw_tail(drive, |
1143 | REQ_IDETAPE_READ, 0, | 1019 | REQ_IDETAPE_READ, 0); |
1144 | tape->merge_bh); | ||
1145 | if (bytes_read < 0) { | 1020 | if (bytes_read < 0) { |
1146 | ide_tape_kfree_buffer(tape); | 1021 | kfree(tape->buf); |
1147 | tape->merge_bh = NULL; | 1022 | tape->buf = NULL; |
1148 | tape->chrdev_dir = IDETAPE_DIR_NONE; | 1023 | tape->chrdev_dir = IDETAPE_DIR_NONE; |
1149 | return bytes_read; | 1024 | return bytes_read; |
1150 | } | 1025 | } |
@@ -1157,8 +1032,6 @@ static int idetape_init_read(ide_drive_t *drive) | |||
1157 | /* called from idetape_chrdev_read() to service a chrdev read request. */ | 1032 | /* called from idetape_chrdev_read() to service a chrdev read request. */ |
1158 | static int idetape_add_chrdev_read_request(ide_drive_t *drive, int blocks) | 1033 | static int idetape_add_chrdev_read_request(ide_drive_t *drive, int blocks) |
1159 | { | 1034 | { |
1160 | idetape_tape_t *tape = drive->driver_data; | ||
1161 | |||
1162 | debug_log(DBG_PROCS, "Enter %s, %d blocks\n", __func__, blocks); | 1035 | debug_log(DBG_PROCS, "Enter %s, %d blocks\n", __func__, blocks); |
1163 | 1036 | ||
1164 | /* If we are at a filemark, return a read length of 0 */ | 1037 | /* If we are at a filemark, return a read length of 0 */ |
@@ -1167,27 +1040,21 @@ static int idetape_add_chrdev_read_request(ide_drive_t *drive, int blocks) | |||
1167 | 1040 | ||
1168 | idetape_init_read(drive); | 1041 | idetape_init_read(drive); |
1169 | 1042 | ||
1170 | return idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, blocks, | 1043 | return idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, blocks); |
1171 | tape->merge_bh); | ||
1172 | } | 1044 | } |
1173 | 1045 | ||
1174 | static void idetape_pad_zeros(ide_drive_t *drive, int bcount) | 1046 | static void idetape_pad_zeros(ide_drive_t *drive, int bcount) |
1175 | { | 1047 | { |
1176 | idetape_tape_t *tape = drive->driver_data; | 1048 | idetape_tape_t *tape = drive->driver_data; |
1177 | struct idetape_bh *bh = tape->merge_bh; | 1049 | |
1178 | int blocks; | 1050 | memset(tape->buf, 0, tape->buffer_size); |
1179 | 1051 | ||
1180 | while (bcount) { | 1052 | while (bcount) { |
1181 | unsigned int count; | 1053 | unsigned int count = min(tape->buffer_size, bcount); |
1182 | 1054 | ||
1183 | count = min(tape->buffer_size, bcount); | 1055 | idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, |
1056 | count / tape->blk_size); | ||
1184 | bcount -= count; | 1057 | bcount -= count; |
1185 | blocks = count / tape->blk_size; | ||
1186 | atomic_set(&bh->b_count, count); | ||
1187 | memset(bh->b_data, 0, atomic_read(&bh->b_count)); | ||
1188 | |||
1189 | idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, blocks, | ||
1190 | tape->merge_bh); | ||
1191 | } | 1058 | } |
1192 | } | 1059 | } |
1193 | 1060 | ||
@@ -1267,7 +1134,7 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op, | |||
1267 | } | 1134 | } |
1268 | 1135 | ||
1269 | if (tape->chrdev_dir == IDETAPE_DIR_READ) { | 1136 | if (tape->chrdev_dir == IDETAPE_DIR_READ) { |
1270 | tape->merge_bh_size = 0; | 1137 | tape->valid = 0; |
1271 | if (test_and_clear_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) | 1138 | if (test_and_clear_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) |
1272 | ++count; | 1139 | ++count; |
1273 | ide_tape_discard_merge_buffer(drive, 0); | 1140 | ide_tape_discard_merge_buffer(drive, 0); |
@@ -1333,20 +1200,20 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf, | |||
1333 | return rc; | 1200 | return rc; |
1334 | if (count == 0) | 1201 | if (count == 0) |
1335 | return (0); | 1202 | return (0); |
1336 | if (tape->merge_bh_size) { | 1203 | if (tape->valid) { |
1337 | actually_read = min((unsigned int)(tape->merge_bh_size), | 1204 | actually_read = min_t(unsigned int, tape->valid, count); |
1338 | (unsigned int)count); | 1205 | if (copy_to_user(buf, tape->cur, actually_read)) |
1339 | if (idetape_copy_stage_to_user(tape, buf, actually_read)) | ||
1340 | ret = -EFAULT; | 1206 | ret = -EFAULT; |
1341 | buf += actually_read; | 1207 | buf += actually_read; |
1342 | tape->merge_bh_size -= actually_read; | ||
1343 | count -= actually_read; | 1208 | count -= actually_read; |
1209 | tape->cur += actually_read; | ||
1210 | tape->valid -= actually_read; | ||
1344 | } | 1211 | } |
1345 | while (count >= tape->buffer_size) { | 1212 | while (count >= tape->buffer_size) { |
1346 | bytes_read = idetape_add_chrdev_read_request(drive, ctl); | 1213 | bytes_read = idetape_add_chrdev_read_request(drive, ctl); |
1347 | if (bytes_read <= 0) | 1214 | if (bytes_read <= 0) |
1348 | goto finish; | 1215 | goto finish; |
1349 | if (idetape_copy_stage_to_user(tape, buf, bytes_read)) | 1216 | if (copy_to_user(buf, tape->cur, bytes_read)) |
1350 | ret = -EFAULT; | 1217 | ret = -EFAULT; |
1351 | buf += bytes_read; | 1218 | buf += bytes_read; |
1352 | count -= bytes_read; | 1219 | count -= bytes_read; |
@@ -1357,10 +1224,11 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf, | |||
1357 | if (bytes_read <= 0) | 1224 | if (bytes_read <= 0) |
1358 | goto finish; | 1225 | goto finish; |
1359 | temp = min((unsigned long)count, (unsigned long)bytes_read); | 1226 | temp = min((unsigned long)count, (unsigned long)bytes_read); |
1360 | if (idetape_copy_stage_to_user(tape, buf, temp)) | 1227 | if (copy_to_user(buf, tape->cur, temp)) |
1361 | ret = -EFAULT; | 1228 | ret = -EFAULT; |
1362 | actually_read += temp; | 1229 | actually_read += temp; |
1363 | tape->merge_bh_size = bytes_read-temp; | 1230 | tape->cur += temp; |
1231 | tape->valid -= temp; | ||
1364 | } | 1232 | } |
1365 | finish: | 1233 | finish: |
1366 | if (!actually_read && test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) { | 1234 | if (!actually_read && test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) { |
@@ -1392,16 +1260,15 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf, | |||
1392 | if (tape->chrdev_dir != IDETAPE_DIR_WRITE) { | 1260 | if (tape->chrdev_dir != IDETAPE_DIR_WRITE) { |
1393 | if (tape->chrdev_dir == IDETAPE_DIR_READ) | 1261 | if (tape->chrdev_dir == IDETAPE_DIR_READ) |
1394 | ide_tape_discard_merge_buffer(drive, 1); | 1262 | ide_tape_discard_merge_buffer(drive, 1); |
1395 | if (tape->merge_bh || tape->merge_bh_size) { | 1263 | if (tape->buf || tape->valid) { |
1396 | printk(KERN_ERR "ide-tape: merge_bh_size " | 1264 | printk(KERN_ERR "ide-tape: valid should be 0 now\n"); |
1397 | "should be 0 now\n"); | 1265 | tape->valid = 0; |
1398 | tape->merge_bh_size = 0; | ||
1399 | } | 1266 | } |
1400 | tape->merge_bh = ide_tape_kmalloc_buffer(tape, 0); | 1267 | tape->buf = kmalloc(tape->buffer_size, GFP_KERNEL); |
1401 | if (!tape->merge_bh) | 1268 | if (!tape->buf) |
1402 | return -ENOMEM; | 1269 | return -ENOMEM; |
1403 | tape->chrdev_dir = IDETAPE_DIR_WRITE; | 1270 | tape->chrdev_dir = IDETAPE_DIR_WRITE; |
1404 | idetape_init_merge_buffer(tape); | 1271 | tape->cur = tape->buf; |
1405 | 1272 | ||
1406 | /* | 1273 | /* |
1407 | * Issue a write 0 command to ensure that DSC handshake is | 1274 | * Issue a write 0 command to ensure that DSC handshake is |
@@ -1411,11 +1278,10 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf, | |||
1411 | */ | 1278 | */ |
1412 | if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) { | 1279 | if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) { |
1413 | ssize_t retval = idetape_queue_rw_tail(drive, | 1280 | ssize_t retval = idetape_queue_rw_tail(drive, |
1414 | REQ_IDETAPE_WRITE, 0, | 1281 | REQ_IDETAPE_WRITE, 0); |
1415 | tape->merge_bh); | ||
1416 | if (retval < 0) { | 1282 | if (retval < 0) { |
1417 | ide_tape_kfree_buffer(tape); | 1283 | kfree(tape->buf); |
1418 | tape->merge_bh = NULL; | 1284 | tape->buf = NULL; |
1419 | tape->chrdev_dir = IDETAPE_DIR_NONE; | 1285 | tape->chrdev_dir = IDETAPE_DIR_NONE; |
1420 | return retval; | 1286 | return retval; |
1421 | } | 1287 | } |
@@ -1423,23 +1289,19 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf, | |||
1423 | } | 1289 | } |
1424 | if (count == 0) | 1290 | if (count == 0) |
1425 | return (0); | 1291 | return (0); |
1426 | if (tape->merge_bh_size) { | 1292 | if (tape->valid < tape->buffer_size) { |
1427 | if (tape->merge_bh_size >= tape->buffer_size) { | 1293 | actually_written = min_t(unsigned int, |
1428 | printk(KERN_ERR "ide-tape: bug: merge buf too big\n"); | 1294 | tape->buffer_size - tape->valid, |
1429 | tape->merge_bh_size = 0; | 1295 | count); |
1430 | } | 1296 | if (copy_from_user(tape->cur, buf, actually_written)) |
1431 | actually_written = min((unsigned int) | 1297 | ret = -EFAULT; |
1432 | (tape->buffer_size - tape->merge_bh_size), | ||
1433 | (unsigned int)count); | ||
1434 | if (idetape_copy_stage_from_user(tape, buf, actually_written)) | ||
1435 | ret = -EFAULT; | ||
1436 | buf += actually_written; | 1298 | buf += actually_written; |
1437 | tape->merge_bh_size += actually_written; | ||
1438 | count -= actually_written; | 1299 | count -= actually_written; |
1300 | tape->cur += actually_written; | ||
1301 | tape->valid += actually_written; | ||
1439 | 1302 | ||
1440 | if (tape->merge_bh_size == tape->buffer_size) { | 1303 | if (tape->valid == tape->buffer_size) { |
1441 | ssize_t retval; | 1304 | ssize_t retval; |
1442 | tape->merge_bh_size = 0; | ||
1443 | retval = idetape_add_chrdev_write_request(drive, ctl); | 1305 | retval = idetape_add_chrdev_write_request(drive, ctl); |
1444 | if (retval <= 0) | 1306 | if (retval <= 0) |
1445 | return (retval); | 1307 | return (retval); |
@@ -1447,7 +1309,7 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf, | |||
1447 | } | 1309 | } |
1448 | while (count >= tape->buffer_size) { | 1310 | while (count >= tape->buffer_size) { |
1449 | ssize_t retval; | 1311 | ssize_t retval; |
1450 | if (idetape_copy_stage_from_user(tape, buf, tape->buffer_size)) | 1312 | if (copy_from_user(tape->cur, buf, tape->buffer_size)) |
1451 | ret = -EFAULT; | 1313 | ret = -EFAULT; |
1452 | buf += tape->buffer_size; | 1314 | buf += tape->buffer_size; |
1453 | count -= tape->buffer_size; | 1315 | count -= tape->buffer_size; |
@@ -1458,9 +1320,10 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf, | |||
1458 | } | 1320 | } |
1459 | if (count) { | 1321 | if (count) { |
1460 | actually_written += count; | 1322 | actually_written += count; |
1461 | if (idetape_copy_stage_from_user(tape, buf, count)) | 1323 | if (copy_from_user(tape->cur, buf, count)) |
1462 | ret = -EFAULT; | 1324 | ret = -EFAULT; |
1463 | tape->merge_bh_size += count; | 1325 | tape->cur += count; |
1326 | tape->valid += count; | ||
1464 | } | 1327 | } |
1465 | return ret ? ret : actually_written; | 1328 | return ret ? ret : actually_written; |
1466 | } | 1329 | } |
@@ -1623,7 +1486,7 @@ static int idetape_chrdev_ioctl(struct inode *inode, struct file *file, | |||
1623 | idetape_flush_tape_buffers(drive); | 1486 | idetape_flush_tape_buffers(drive); |
1624 | } | 1487 | } |
1625 | if (cmd == MTIOCGET || cmd == MTIOCPOS) { | 1488 | if (cmd == MTIOCGET || cmd == MTIOCPOS) { |
1626 | block_offset = tape->merge_bh_size / | 1489 | block_offset = tape->valid / |
1627 | (tape->blk_size * tape->user_bs_factor); | 1490 | (tape->blk_size * tape->user_bs_factor); |
1628 | position = idetape_read_position(drive); | 1491 | position = idetape_read_position(drive); |
1629 | if (position < 0) | 1492 | if (position < 0) |
@@ -1771,12 +1634,12 @@ static void idetape_write_release(ide_drive_t *drive, unsigned int minor) | |||
1771 | idetape_tape_t *tape = drive->driver_data; | 1634 | idetape_tape_t *tape = drive->driver_data; |
1772 | 1635 | ||
1773 | ide_tape_flush_merge_buffer(drive); | 1636 | ide_tape_flush_merge_buffer(drive); |
1774 | tape->merge_bh = ide_tape_kmalloc_buffer(tape, 1); | 1637 | tape->buf = kmalloc(tape->buffer_size, GFP_KERNEL); |
1775 | if (tape->merge_bh != NULL) { | 1638 | if (tape->buf != NULL) { |
1776 | idetape_pad_zeros(drive, tape->blk_size * | 1639 | idetape_pad_zeros(drive, tape->blk_size * |
1777 | (tape->user_bs_factor - 1)); | 1640 | (tape->user_bs_factor - 1)); |
1778 | ide_tape_kfree_buffer(tape); | 1641 | kfree(tape->buf); |
1779 | tape->merge_bh = NULL; | 1642 | tape->buf = NULL; |
1780 | } | 1643 | } |
1781 | idetape_write_filemark(drive); | 1644 | idetape_write_filemark(drive); |
1782 | idetape_flush_tape_buffers(drive); | 1645 | idetape_flush_tape_buffers(drive); |
@@ -2042,7 +1905,7 @@ static void ide_tape_release(struct device *dev) | |||
2042 | ide_drive_t *drive = tape->drive; | 1905 | ide_drive_t *drive = tape->drive; |
2043 | struct gendisk *g = tape->disk; | 1906 | struct gendisk *g = tape->disk; |
2044 | 1907 | ||
2045 | BUG_ON(tape->merge_bh_size); | 1908 | BUG_ON(tape->valid); |
2046 | 1909 | ||
2047 | drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP; | 1910 | drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP; |
2048 | drive->driver_data = NULL; | 1911 | drive->driver_data = NULL; |