aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide-tape.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2009-04-18 19:46:03 -0400
committerTejun Heo <tj@kernel.org>2009-04-18 19:46:03 -0400
commit07bd9686c50c2b1f10e48089d4fb836a971f5177 (patch)
tree8a7b822752850ad43508d8c358ed45ca030a1894 /drivers/ide/ide-tape.c
parent6bb11dd14f70228f8dab25fd25dabeb9bc74926d (diff)
ide-tape: simplify read/write functions
Impact: cleanup idetape_chrdev_read/write() functions are unnecessarily complex when everything can be handled in a single loop. Collapse idetape_add_chrdev_read/write_request() into the rw functions and simplify the implementation. Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'drivers/ide/ide-tape.c')
-rw-r--r--drivers/ide/ide-tape.c149
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. */
957static 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
964static void ide_tape_flush_merge_buffer(ide_drive_t *drive) 956static 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. */
1035static 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
1048static void idetape_pad_zeros(ide_drive_t *drive, int bcount) 1026static 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 }
1235finish: 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
1246static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf, 1216static 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
1308static int idetape_write_filemark(ide_drive_t *drive) 1259static int idetape_write_filemark(ide_drive_t *drive)