diff options
-rw-r--r-- | drivers/ide/ide-tape.c | 149 |
1 files changed, 50 insertions, 99 deletions
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index d5e9bb286e30..2599579e4174 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c | |||
@@ -953,14 +953,6 @@ static void idetape_create_space_cmd(struct ide_atapi_pc *pc, int count, u8 cmd) | |||
953 | pc->flags |= PC_FLAG_WAIT_FOR_DSC; | 953 | pc->flags |= PC_FLAG_WAIT_FOR_DSC; |
954 | } | 954 | } |
955 | 955 | ||
956 | /* Queue up a character device originated write request. */ | ||
957 | static int idetape_add_chrdev_write_request(ide_drive_t *drive, int size) | ||
958 | { | ||
959 | debug_log(DBG_CHRDEV, "Enter %s\n", __func__); | ||
960 | |||
961 | return idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, size); | ||
962 | } | ||
963 | |||
964 | static void ide_tape_flush_merge_buffer(ide_drive_t *drive) | 956 | static void ide_tape_flush_merge_buffer(ide_drive_t *drive) |
965 | { | 957 | { |
966 | idetape_tape_t *tape = drive->driver_data; | 958 | idetape_tape_t *tape = drive->driver_data; |
@@ -974,7 +966,7 @@ static void ide_tape_flush_merge_buffer(ide_drive_t *drive) | |||
974 | size_t aligned = roundup(tape->valid, tape->blk_size); | 966 | size_t aligned = roundup(tape->valid, tape->blk_size); |
975 | 967 | ||
976 | memset(tape->cur, 0, aligned - tape->valid); | 968 | memset(tape->cur, 0, aligned - tape->valid); |
977 | idetape_add_chrdev_write_request(drive, aligned); | 969 | idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, aligned); |
978 | kfree(tape->buf); | 970 | kfree(tape->buf); |
979 | tape->buf = NULL; | 971 | tape->buf = NULL; |
980 | } | 972 | } |
@@ -1031,20 +1023,6 @@ static int idetape_init_rw(ide_drive_t *drive, int dir) | |||
1031 | return 0; | 1023 | return 0; |
1032 | } | 1024 | } |
1033 | 1025 | ||
1034 | /* called from idetape_chrdev_read() to service a chrdev read request. */ | ||
1035 | static int idetape_add_chrdev_read_request(ide_drive_t *drive, int size) | ||
1036 | { | ||
1037 | debug_log(DBG_PROCS, "Enter %s, %d bytes\n", __func__, size); | ||
1038 | |||
1039 | /* If we are at a filemark, return a read length of 0 */ | ||
1040 | if (test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) | ||
1041 | return 0; | ||
1042 | |||
1043 | idetape_init_rw(drive, IDETAPE_DIR_READ); | ||
1044 | |||
1045 | return idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, size); | ||
1046 | } | ||
1047 | |||
1048 | static void idetape_pad_zeros(ide_drive_t *drive, int bcount) | 1026 | static void idetape_pad_zeros(ide_drive_t *drive, int bcount) |
1049 | { | 1027 | { |
1050 | idetape_tape_t *tape = drive->driver_data; | 1028 | idetape_tape_t *tape = drive->driver_data; |
@@ -1184,8 +1162,9 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf, | |||
1184 | { | 1162 | { |
1185 | struct ide_tape_obj *tape = file->private_data; | 1163 | struct ide_tape_obj *tape = file->private_data; |
1186 | ide_drive_t *drive = tape->drive; | 1164 | ide_drive_t *drive = tape->drive; |
1187 | ssize_t bytes_read, temp, actually_read = 0, rc; | 1165 | size_t done = 0; |
1188 | ssize_t ret = 0; | 1166 | ssize_t ret = 0; |
1167 | int rc; | ||
1189 | 1168 | ||
1190 | debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count); | 1169 | debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count); |
1191 | 1170 | ||
@@ -1195,52 +1174,43 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf, | |||
1195 | (count % tape->blk_size) == 0) | 1174 | (count % tape->blk_size) == 0) |
1196 | tape->user_bs_factor = count / tape->blk_size; | 1175 | tape->user_bs_factor = count / tape->blk_size; |
1197 | } | 1176 | } |
1177 | |||
1198 | rc = idetape_init_rw(drive, IDETAPE_DIR_READ); | 1178 | rc = idetape_init_rw(drive, IDETAPE_DIR_READ); |
1199 | if (rc < 0) | 1179 | if (rc < 0) |
1200 | return rc; | 1180 | return rc; |
1201 | if (count == 0) | 1181 | |
1202 | return (0); | 1182 | while (done < count) { |
1203 | if (tape->valid) { | 1183 | size_t todo; |
1204 | actually_read = min_t(unsigned int, tape->valid, count); | 1184 | |
1205 | if (copy_to_user(buf, tape->cur, actually_read)) | 1185 | /* refill if staging buffer is empty */ |
1206 | ret = -EFAULT; | 1186 | if (!tape->valid) { |
1207 | buf += actually_read; | 1187 | /* If we are at a filemark, nothing more to read */ |
1208 | count -= actually_read; | 1188 | if (test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) |
1209 | tape->cur += actually_read; | 1189 | break; |
1210 | tape->valid -= actually_read; | 1190 | /* read */ |
1211 | } | 1191 | if (idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, |
1212 | while (count >= tape->buffer_size) { | 1192 | tape->buffer_size) <= 0) |
1213 | bytes_read = idetape_add_chrdev_read_request(drive, | 1193 | break; |
1214 | tape->buffer_size); | 1194 | } |
1215 | if (bytes_read <= 0) | 1195 | |
1216 | goto finish; | 1196 | /* copy out */ |
1217 | if (copy_to_user(buf, tape->cur, bytes_read)) | 1197 | todo = min_t(size_t, count - done, tape->valid); |
1218 | ret = -EFAULT; | 1198 | if (copy_to_user(buf + done, tape->cur, todo)) |
1219 | buf += bytes_read; | ||
1220 | count -= bytes_read; | ||
1221 | actually_read += bytes_read; | ||
1222 | } | ||
1223 | if (count) { | ||
1224 | bytes_read = idetape_add_chrdev_read_request(drive, | ||
1225 | tape->buffer_size); | ||
1226 | if (bytes_read <= 0) | ||
1227 | goto finish; | ||
1228 | temp = min((unsigned long)count, (unsigned long)bytes_read); | ||
1229 | if (copy_to_user(buf, tape->cur, temp)) | ||
1230 | ret = -EFAULT; | 1199 | ret = -EFAULT; |
1231 | actually_read += temp; | 1200 | |
1232 | tape->cur += temp; | 1201 | tape->cur += todo; |
1233 | tape->valid -= temp; | 1202 | tape->valid -= todo; |
1203 | done += todo; | ||
1234 | } | 1204 | } |
1235 | finish: | 1205 | |
1236 | if (!actually_read && test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) { | 1206 | if (!done && test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) { |
1237 | debug_log(DBG_SENSE, "%s: spacing over filemark\n", tape->name); | 1207 | debug_log(DBG_SENSE, "%s: spacing over filemark\n", tape->name); |
1238 | 1208 | ||
1239 | idetape_space_over_filemarks(drive, MTFSF, 1); | 1209 | idetape_space_over_filemarks(drive, MTFSF, 1); |
1240 | return 0; | 1210 | return 0; |
1241 | } | 1211 | } |
1242 | 1212 | ||
1243 | return ret ? ret : actually_read; | 1213 | return ret ? ret : done; |
1244 | } | 1214 | } |
1245 | 1215 | ||
1246 | static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf, | 1216 | static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf, |
@@ -1248,7 +1218,7 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf, | |||
1248 | { | 1218 | { |
1249 | struct ide_tape_obj *tape = file->private_data; | 1219 | struct ide_tape_obj *tape = file->private_data; |
1250 | ide_drive_t *drive = tape->drive; | 1220 | ide_drive_t *drive = tape->drive; |
1251 | ssize_t actually_written = 0; | 1221 | size_t done = 0; |
1252 | ssize_t ret = 0; | 1222 | ssize_t ret = 0; |
1253 | int rc; | 1223 | int rc; |
1254 | 1224 | ||
@@ -1262,47 +1232,28 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf, | |||
1262 | rc = idetape_init_rw(drive, IDETAPE_DIR_WRITE); | 1232 | rc = idetape_init_rw(drive, IDETAPE_DIR_WRITE); |
1263 | if (rc < 0) | 1233 | if (rc < 0) |
1264 | return rc; | 1234 | return rc; |
1265 | if (count == 0) | 1235 | |
1266 | return (0); | 1236 | while (done < count) { |
1267 | if (tape->valid < tape->buffer_size) { | 1237 | size_t todo; |
1268 | actually_written = min_t(unsigned int, | 1238 | |
1269 | tape->buffer_size - tape->valid, | 1239 | /* flush if staging buffer is full */ |
1270 | count); | 1240 | if (tape->valid == tape->buffer_size && |
1271 | if (copy_from_user(tape->cur, buf, actually_written)) | 1241 | idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, |
1272 | ret = -EFAULT; | 1242 | tape->buffer_size) <= 0) |
1273 | buf += actually_written; | 1243 | return rc; |
1274 | count -= actually_written; | 1244 | |
1275 | tape->cur += actually_written; | 1245 | /* copy in */ |
1276 | tape->valid += actually_written; | 1246 | todo = min_t(size_t, count - done, |
1277 | 1247 | tape->buffer_size - tape->valid); | |
1278 | if (tape->valid == tape->buffer_size) { | 1248 | if (copy_from_user(tape->cur, buf + done, todo)) |
1279 | ssize_t retval; | ||
1280 | retval = idetape_add_chrdev_write_request(drive, | ||
1281 | tape->buffer_size); | ||
1282 | if (retval <= 0) | ||
1283 | return (retval); | ||
1284 | } | ||
1285 | } | ||
1286 | while (count >= tape->buffer_size) { | ||
1287 | ssize_t retval; | ||
1288 | if (copy_from_user(tape->cur, buf, tape->buffer_size)) | ||
1289 | ret = -EFAULT; | ||
1290 | buf += tape->buffer_size; | ||
1291 | count -= tape->buffer_size; | ||
1292 | retval = idetape_add_chrdev_write_request(drive, | ||
1293 | tape->buffer_size); | ||
1294 | actually_written += tape->buffer_size; | ||
1295 | if (retval <= 0) | ||
1296 | return (retval); | ||
1297 | } | ||
1298 | if (count) { | ||
1299 | actually_written += count; | ||
1300 | if (copy_from_user(tape->cur, buf, count)) | ||
1301 | ret = -EFAULT; | 1249 | ret = -EFAULT; |
1302 | tape->cur += count; | 1250 | |
1303 | tape->valid += count; | 1251 | tape->cur += todo; |
1252 | tape->valid += todo; | ||
1253 | done += todo; | ||
1304 | } | 1254 | } |
1305 | return ret ? ret : actually_written; | 1255 | |
1256 | return ret ? ret : done; | ||
1306 | } | 1257 | } |
1307 | 1258 | ||
1308 | static int idetape_write_filemark(ide_drive_t *drive) | 1259 | static int idetape_write_filemark(ide_drive_t *drive) |