aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide-tape.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2009-04-18 19:46:02 -0400
committerTejun Heo <tj@kernel.org>2009-04-18 19:46:02 -0400
commit35ab8d3251833e4052aa64b09b08195e949518c7 (patch)
treec5502cb57b78625780809a3b65888fdc653b8248 /drivers/ide/ide-tape.c
parentb3071d190d6757b14af002a9d79832f12de61bce (diff)
ide-tape: use single continuous buffer
Impact: simpler buffer allocation and handling, kills OOM, fix DMA transfers ide-tape has its own multiple buffer mechanism using struct idetape_bh. It allocates buffer with decreasing order-of-two allocations so that it results in minimum number of segments. However, the implementation is quite complex and works in a way that no other block or ide driver works necessitating a lot of special case handling. The benefit this complex allocation scheme brings is questionable as PIO or DMA the number of segments (16 maximum) doesn't make any noticeable difference and it also doesn't negate the need for multiple order allocation which can fail under memory pressure or high fragmentation although it does lower the highest order necessary by one when the buffer size isn't power of two. As the first step to remove the custom buffer management, this patch makes ide-tape allocate single continous buffer. The maximum order is four. I doubt the change would cause any trouble but if it ever matters, it should be converted to regular sg mechanism like everyone else and even in that case dropping custom buffer handling and moving to standard mechanism first make sense as an intermediate step. This patch makes the first bh to contain the whole buffer and drops multi bh handling code. Following patches will make further changes. This patch has the side effect of killing OOM triggered by allocation path and fixing DMA transfers. Previously, bug in alloc path triggered OOM on command issue and commands were passed to DMA engine without DMA-mapping all the segments. Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'drivers/ide/ide-tape.c')
-rw-r--r--drivers/ide/ide-tape.c256
1 files changed, 58 insertions, 198 deletions
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 8226d52504d0..b2afbc7bcb6b 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -134,7 +134,6 @@ enum {
134struct idetape_bh { 134struct idetape_bh {
135 u32 b_size; 135 u32 b_size;
136 atomic_t b_count; 136 atomic_t b_count;
137 struct idetape_bh *b_reqnext;
138 char *b_data; 137 char *b_data;
139}; 138};
140 139
@@ -228,10 +227,6 @@ typedef struct ide_tape_obj {
228 char *b_data; 227 char *b_data;
229 int b_count; 228 int b_count;
230 229
231 int pages_per_buffer;
232 /* Wasted space in each stage */
233 int excess_bh_size;
234
235 /* Measures average tape speed */ 230 /* Measures average tape speed */
236 unsigned long avg_time; 231 unsigned long avg_time;
237 int avg_size; 232 int avg_size;
@@ -303,9 +298,7 @@ static int idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
303 struct idetape_bh *bh = pc->bh; 298 struct idetape_bh *bh = pc->bh;
304 int count; 299 int count;
305 300
306 while (bcount) { 301 if (bcount && bh) {
307 if (bh == NULL)
308 break;
309 count = min( 302 count = min(
310 (unsigned int)(bh->b_size - atomic_read(&bh->b_count)), 303 (unsigned int)(bh->b_size - atomic_read(&bh->b_count)),
311 bcount); 304 bcount);
@@ -313,15 +306,10 @@ static int idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
313 atomic_read(&bh->b_count), count); 306 atomic_read(&bh->b_count), count);
314 bcount -= count; 307 bcount -= count;
315 atomic_add(count, &bh->b_count); 308 atomic_add(count, &bh->b_count);
316 if (atomic_read(&bh->b_count) == bh->b_size) { 309 if (atomic_read(&bh->b_count) == bh->b_size)
317 bh = bh->b_reqnext; 310 pc->bh = NULL;
318 if (bh)
319 atomic_set(&bh->b_count, 0);
320 }
321 } 311 }
322 312
323 pc->bh = bh;
324
325 return bcount; 313 return bcount;
326} 314}
327 315
@@ -331,22 +319,14 @@ static int idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
331 struct idetape_bh *bh = pc->bh; 319 struct idetape_bh *bh = pc->bh;
332 int count; 320 int count;
333 321
334 while (bcount) { 322 if (bcount && bh) {
335 if (bh == NULL)
336 break;
337 count = min((unsigned int)pc->b_count, (unsigned int)bcount); 323 count = min((unsigned int)pc->b_count, (unsigned int)bcount);
338 drive->hwif->tp_ops->output_data(drive, NULL, pc->b_data, count); 324 drive->hwif->tp_ops->output_data(drive, NULL, pc->b_data, count);
339 bcount -= count; 325 bcount -= count;
340 pc->b_data += count; 326 pc->b_data += count;
341 pc->b_count -= count; 327 pc->b_count -= count;
342 if (!pc->b_count) { 328 if (!pc->b_count)
343 bh = bh->b_reqnext; 329 pc->bh = NULL;
344 pc->bh = bh;
345 if (bh) {
346 pc->b_data = bh->b_data;
347 pc->b_count = atomic_read(&bh->b_count);
348 }
349 }
350 } 330 }
351 331
352 return bcount; 332 return bcount;
@@ -355,24 +335,20 @@ static int idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
355static void idetape_update_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc) 335static void idetape_update_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc)
356{ 336{
357 struct idetape_bh *bh = pc->bh; 337 struct idetape_bh *bh = pc->bh;
358 int count;
359 unsigned int bcount = pc->xferred; 338 unsigned int bcount = pc->xferred;
360 339
361 if (pc->flags & PC_FLAG_WRITING) 340 if (pc->flags & PC_FLAG_WRITING)
362 return; 341 return;
363 while (bcount) { 342 if (bcount) {
364 if (bh == NULL) { 343 if (bh == NULL || bcount > bh->b_size) {
365 printk(KERN_ERR "ide-tape: bh == NULL in %s\n", 344 printk(KERN_ERR "ide-tape: bh == NULL in %s\n",
366 __func__); 345 __func__);
367 return; 346 return;
368 } 347 }
369 count = min((unsigned int)bh->b_size, (unsigned int)bcount); 348 atomic_set(&bh->b_count, bcount);
370 atomic_set(&bh->b_count, count);
371 if (atomic_read(&bh->b_count) == bh->b_size) 349 if (atomic_read(&bh->b_count) == bh->b_size)
372 bh = bh->b_reqnext; 350 pc->bh = NULL;
373 bcount -= count;
374 } 351 }
375 pc->bh = bh;
376} 352}
377 353
378/* 354/*
@@ -439,24 +415,10 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense)
439/* Free data buffers completely. */ 415/* Free data buffers completely. */
440static void ide_tape_kfree_buffer(idetape_tape_t *tape) 416static void ide_tape_kfree_buffer(idetape_tape_t *tape)
441{ 417{
442 struct idetape_bh *prev_bh, *bh = tape->merge_bh; 418 struct idetape_bh *bh = tape->merge_bh;
443
444 while (bh) {
445 u32 size = bh->b_size;
446
447 while (size) {
448 unsigned int order = fls(size >> PAGE_SHIFT)-1;
449
450 if (bh->b_data)
451 free_pages((unsigned long)bh->b_data, order);
452 419
453 size &= (order-1); 420 kfree(bh->b_data);
454 bh->b_data += (1 << order) * PAGE_SIZE; 421 kfree(bh);
455 }
456 prev_bh = bh;
457 bh = bh->b_reqnext;
458 kfree(prev_bh);
459 }
460} 422}
461 423
462static void ide_tape_handle_dsc(ide_drive_t *); 424static void ide_tape_handle_dsc(ide_drive_t *);
@@ -861,117 +823,50 @@ out:
861} 823}
862 824
863/* 825/*
864 * The function below uses __get_free_pages to allocate a data buffer of size 826 * It returns a pointer to the newly allocated buffer, or NULL in case
865 * tape->buffer_size (or a bit more). We attempt to combine sequential pages as 827 * of failure.
866 * much as possible.
867 *
868 * It returns a pointer to the newly allocated buffer, or NULL in case of
869 * failure.
870 */ 828 */
871static struct idetape_bh *ide_tape_kmalloc_buffer(idetape_tape_t *tape, 829static struct idetape_bh *ide_tape_kmalloc_buffer(idetape_tape_t *tape,
872 int full, int clear) 830 int full)
873{ 831{
874 struct idetape_bh *prev_bh, *bh, *merge_bh; 832 struct idetape_bh *bh;
875 int pages = tape->pages_per_buffer;
876 unsigned int order, b_allocd;
877 char *b_data = NULL;
878
879 merge_bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
880 bh = merge_bh;
881 if (bh == NULL)
882 goto abort;
883
884 order = fls(pages) - 1;
885 bh->b_data = (char *) __get_free_pages(GFP_KERNEL, order);
886 if (!bh->b_data)
887 goto abort;
888 b_allocd = (1 << order) * PAGE_SIZE;
889 pages &= (order-1);
890
891 if (clear)
892 memset(bh->b_data, 0, b_allocd);
893 bh->b_reqnext = NULL;
894 bh->b_size = b_allocd;
895 atomic_set(&bh->b_count, full ? bh->b_size : 0);
896 833
897 while (pages) { 834 bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
898 order = fls(pages) - 1; 835 if (!bh)
899 b_data = (char *) __get_free_pages(GFP_KERNEL, order); 836 return NULL;
900 if (!b_data)
901 goto abort;
902 b_allocd = (1 << order) * PAGE_SIZE;
903
904 if (clear)
905 memset(b_data, 0, b_allocd);
906
907 /* newly allocated page frames below buffer header or ...*/
908 if (bh->b_data == b_data + b_allocd) {
909 bh->b_size += b_allocd;
910 bh->b_data -= b_allocd;
911 if (full)
912 atomic_add(b_allocd, &bh->b_count);
913 continue;
914 }
915 /* they are above the header */
916 if (b_data == bh->b_data + bh->b_size) {
917 bh->b_size += b_allocd;
918 if (full)
919 atomic_add(b_allocd, &bh->b_count);
920 continue;
921 }
922 prev_bh = bh;
923 bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
924 if (!bh) {
925 free_pages((unsigned long) b_data, order);
926 goto abort;
927 }
928 bh->b_reqnext = NULL;
929 bh->b_data = b_data;
930 bh->b_size = b_allocd;
931 atomic_set(&bh->b_count, full ? bh->b_size : 0);
932 prev_bh->b_reqnext = bh;
933 837
934 pages &= (order-1); 838 bh->b_data = kmalloc(tape->buffer_size, GFP_KERNEL);
839 if (!bh->b_data) {
840 kfree(bh);
841 return NULL;
935 } 842 }
936 843
937 bh->b_size -= tape->excess_bh_size; 844 bh->b_size = tape->buffer_size;
938 if (full) 845 atomic_set(&bh->b_count, full ? bh->b_size : 0);
939 atomic_sub(tape->excess_bh_size, &bh->b_count); 846
940 return merge_bh; 847 return bh;
941abort:
942 ide_tape_kfree_buffer(tape);
943 return NULL;
944} 848}
945 849
946static int idetape_copy_stage_from_user(idetape_tape_t *tape, 850static int idetape_copy_stage_from_user(idetape_tape_t *tape,
947 const char __user *buf, int n) 851 const char __user *buf, int n)
948{ 852{
949 struct idetape_bh *bh = tape->bh; 853 struct idetape_bh *bh = tape->bh;
950 int count;
951 int ret = 0; 854 int ret = 0;
952 855
953 while (n) { 856 if (n) {
954 if (bh == NULL) { 857 if (bh == NULL || n > bh->b_size - atomic_read(&bh->b_count)) {
955 printk(KERN_ERR "ide-tape: bh == NULL in %s\n", 858 printk(KERN_ERR "ide-tape: bh == NULL in %s\n",
956 __func__); 859 __func__);
957 return 1; 860 return 1;
958 } 861 }
959 count = min((unsigned int)
960 (bh->b_size - atomic_read(&bh->b_count)),
961 (unsigned int)n);
962 if (copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf, 862 if (copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf,
963 count)) 863 n))
964 ret = 1; 864 ret = 1;
965 n -= count; 865 atomic_add(n, &bh->b_count);
966 atomic_add(count, &bh->b_count); 866 if (atomic_read(&bh->b_count) == bh->b_size)
967 buf += count; 867 tape->bh = NULL;
968 if (atomic_read(&bh->b_count) == bh->b_size) {
969 bh = bh->b_reqnext;
970 if (bh)
971 atomic_set(&bh->b_count, 0);
972 }
973 } 868 }
974 tape->bh = bh; 869
975 return ret; 870 return ret;
976} 871}
977 872
@@ -979,30 +874,20 @@ static int idetape_copy_stage_to_user(idetape_tape_t *tape, char __user *buf,
979 int n) 874 int n)
980{ 875{
981 struct idetape_bh *bh = tape->bh; 876 struct idetape_bh *bh = tape->bh;
982 int count;
983 int ret = 0; 877 int ret = 0;
984 878
985 while (n) { 879 if (n) {
986 if (bh == NULL) { 880 if (bh == NULL || n > tape->b_count) {
987 printk(KERN_ERR "ide-tape: bh == NULL in %s\n", 881 printk(KERN_ERR "ide-tape: bh == NULL in %s\n",
988 __func__); 882 __func__);
989 return 1; 883 return 1;
990 } 884 }
991 count = min(tape->b_count, n); 885 if (copy_to_user(buf, tape->b_data, n))
992 if (copy_to_user(buf, tape->b_data, count))
993 ret = 1; 886 ret = 1;
994 n -= count; 887 tape->b_data += n;
995 tape->b_data += count; 888 tape->b_count -= n;
996 tape->b_count -= count; 889 if (!tape->b_count)
997 buf += count; 890 tape->bh = NULL;
998 if (!tape->b_count) {
999 bh = bh->b_reqnext;
1000 tape->bh = bh;
1001 if (bh) {
1002 tape->b_data = bh->b_data;
1003 tape->b_count = atomic_read(&bh->b_count);
1004 }
1005 }
1006 } 891 }
1007 return ret; 892 return ret;
1008} 893}
@@ -1254,7 +1139,7 @@ static int idetape_add_chrdev_write_request(ide_drive_t *drive, int blocks)
1254static void ide_tape_flush_merge_buffer(ide_drive_t *drive) 1139static void ide_tape_flush_merge_buffer(ide_drive_t *drive)
1255{ 1140{
1256 idetape_tape_t *tape = drive->driver_data; 1141 idetape_tape_t *tape = drive->driver_data;
1257 int blocks, min; 1142 int blocks;
1258 struct idetape_bh *bh; 1143 struct idetape_bh *bh;
1259 1144
1260 if (tape->chrdev_dir != IDETAPE_DIR_WRITE) { 1145 if (tape->chrdev_dir != IDETAPE_DIR_WRITE) {
@@ -1269,31 +1154,16 @@ static void ide_tape_flush_merge_buffer(ide_drive_t *drive)
1269 if (tape->merge_bh_size) { 1154 if (tape->merge_bh_size) {
1270 blocks = tape->merge_bh_size / tape->blk_size; 1155 blocks = tape->merge_bh_size / tape->blk_size;
1271 if (tape->merge_bh_size % tape->blk_size) { 1156 if (tape->merge_bh_size % tape->blk_size) {
1272 unsigned int i; 1157 unsigned int i = tape->blk_size -
1273 1158 tape->merge_bh_size % tape->blk_size;
1274 blocks++; 1159 blocks++;
1275 i = tape->blk_size - tape->merge_bh_size %
1276 tape->blk_size;
1277 bh = tape->bh->b_reqnext;
1278 while (bh) {
1279 atomic_set(&bh->b_count, 0);
1280 bh = bh->b_reqnext;
1281 }
1282 bh = tape->bh; 1160 bh = tape->bh;
1283 while (i) { 1161 if (bh) {
1284 if (bh == NULL) {
1285 printk(KERN_INFO "ide-tape: bug,"
1286 " bh NULL\n");
1287 break;
1288 }
1289 min = min(i, (unsigned int)(bh->b_size -
1290 atomic_read(&bh->b_count)));
1291 memset(bh->b_data + atomic_read(&bh->b_count), 1162 memset(bh->b_data + atomic_read(&bh->b_count),
1292 0, min); 1163 0, i);
1293 atomic_add(min, &bh->b_count); 1164 atomic_add(i, &bh->b_count);
1294 i -= min; 1165 } else
1295 bh = bh->b_reqnext; 1166 printk(KERN_INFO "ide-tape: bug, bh NULL\n");
1296 }
1297 } 1167 }
1298 (void) idetape_add_chrdev_write_request(drive, blocks); 1168 (void) idetape_add_chrdev_write_request(drive, blocks);
1299 tape->merge_bh_size = 0; 1169 tape->merge_bh_size = 0;
@@ -1321,7 +1191,7 @@ static int idetape_init_read(ide_drive_t *drive)
1321 " 0 now\n"); 1191 " 0 now\n");
1322 tape->merge_bh_size = 0; 1192 tape->merge_bh_size = 0;
1323 } 1193 }
1324 tape->merge_bh = ide_tape_kmalloc_buffer(tape, 0, 0); 1194 tape->merge_bh = ide_tape_kmalloc_buffer(tape, 0);
1325 if (!tape->merge_bh) 1195 if (!tape->merge_bh)
1326 return -ENOMEM; 1196 return -ENOMEM;
1327 tape->chrdev_dir = IDETAPE_DIR_READ; 1197 tape->chrdev_dir = IDETAPE_DIR_READ;
@@ -1368,23 +1238,18 @@ static int idetape_add_chrdev_read_request(ide_drive_t *drive, int blocks)
1368static void idetape_pad_zeros(ide_drive_t *drive, int bcount) 1238static void idetape_pad_zeros(ide_drive_t *drive, int bcount)
1369{ 1239{
1370 idetape_tape_t *tape = drive->driver_data; 1240 idetape_tape_t *tape = drive->driver_data;
1371 struct idetape_bh *bh; 1241 struct idetape_bh *bh = tape->merge_bh;
1372 int blocks; 1242 int blocks;
1373 1243
1374 while (bcount) { 1244 while (bcount) {
1375 unsigned int count; 1245 unsigned int count;
1376 1246
1377 bh = tape->merge_bh;
1378 count = min(tape->buffer_size, bcount); 1247 count = min(tape->buffer_size, bcount);
1379 bcount -= count; 1248 bcount -= count;
1380 blocks = count / tape->blk_size; 1249 blocks = count / tape->blk_size;
1381 while (count) { 1250 atomic_set(&bh->b_count, count);
1382 atomic_set(&bh->b_count, 1251 memset(bh->b_data, 0, atomic_read(&bh->b_count));
1383 min(count, (unsigned int)bh->b_size)); 1252
1384 memset(bh->b_data, 0, atomic_read(&bh->b_count));
1385 count -= atomic_read(&bh->b_count);
1386 bh = bh->b_reqnext;
1387 }
1388 idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, blocks, 1253 idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, blocks,
1389 tape->merge_bh); 1254 tape->merge_bh);
1390 } 1255 }
@@ -1596,7 +1461,7 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
1596 "should be 0 now\n"); 1461 "should be 0 now\n");
1597 tape->merge_bh_size = 0; 1462 tape->merge_bh_size = 0;
1598 } 1463 }
1599 tape->merge_bh = ide_tape_kmalloc_buffer(tape, 0, 0); 1464 tape->merge_bh = ide_tape_kmalloc_buffer(tape, 0);
1600 if (!tape->merge_bh) 1465 if (!tape->merge_bh)
1601 return -ENOMEM; 1466 return -ENOMEM;
1602 tape->chrdev_dir = IDETAPE_DIR_WRITE; 1467 tape->chrdev_dir = IDETAPE_DIR_WRITE;
@@ -1970,7 +1835,7 @@ static void idetape_write_release(ide_drive_t *drive, unsigned int minor)
1970 idetape_tape_t *tape = drive->driver_data; 1835 idetape_tape_t *tape = drive->driver_data;
1971 1836
1972 ide_tape_flush_merge_buffer(drive); 1837 ide_tape_flush_merge_buffer(drive);
1973 tape->merge_bh = ide_tape_kmalloc_buffer(tape, 1, 0); 1838 tape->merge_bh = ide_tape_kmalloc_buffer(tape, 1);
1974 if (tape->merge_bh != NULL) { 1839 if (tape->merge_bh != NULL) {
1975 idetape_pad_zeros(drive, tape->blk_size * 1840 idetape_pad_zeros(drive, tape->blk_size *
1976 (tape->user_bs_factor - 1)); 1841 (tape->user_bs_factor - 1));
@@ -2201,11 +2066,6 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
2201 tape->buffer_size = *ctl * tape->blk_size; 2066 tape->buffer_size = *ctl * tape->blk_size;
2202 } 2067 }
2203 buffer_size = tape->buffer_size; 2068 buffer_size = tape->buffer_size;
2204 tape->pages_per_buffer = buffer_size / PAGE_SIZE;
2205 if (buffer_size % PAGE_SIZE) {
2206 tape->pages_per_buffer++;
2207 tape->excess_bh_size = PAGE_SIZE - buffer_size % PAGE_SIZE;
2208 }
2209 2069
2210 /* select the "best" DSC read/write polling freq */ 2070 /* select the "best" DSC read/write polling freq */
2211 speed = max(*(u16 *)&tape->caps[14], *(u16 *)&tape->caps[8]); 2071 speed = max(*(u16 *)&tape->caps[14], *(u16 *)&tape->caps[8]);