aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide-tape.c
diff options
context:
space:
mode:
authorBorislav Petkov <petkovbb@googlemail.com>2008-04-27 09:38:33 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-04-27 09:38:33 -0400
commitd01dbc3b85d57f3ab89be4291d4739152bb1713a (patch)
treec08ebdac853f2abbf3bf41f4c056953d643dbdad /drivers/ide/ide-tape.c
parenta997a4356ba33dcb9c061677d5943794a29489e8 (diff)
ide-tape: improve buffer pages freeing strategy
Instead of freeing pages one by one, free them 2^order-wise. Also, mv __idetape_kfree_stage() to ide_tape_kfree_buffer(). [bart: add updating bh->b_data] Signed-off-by: Borislav Petkov <petkovbb@gmail.com> Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide/ide-tape.c')
-rw-r--r--drivers/ide/ide-tape.c38
1 files changed, 20 insertions, 18 deletions
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index ea46ed8d0447..4e93a82f57ed 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -583,20 +583,22 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense)
583 } 583 }
584} 584}
585 585
586/* Free a stage along with its related buffers completely. */ 586/* Free data buffers completely. */
587static void __idetape_kfree_stage(idetape_stage_t *stage) 587static void ide_tape_kfree_buffer(idetape_stage_t *stage)
588{ 588{
589 struct idetape_bh *prev_bh, *bh = stage->bh; 589 struct idetape_bh *prev_bh, *bh = stage->bh;
590 int size; 590
591 591 while (bh) {
592 while (bh != NULL) { 592 u32 size = bh->b_size;
593 if (bh->b_data != NULL) { 593
594 size = (int) bh->b_size; 594 while (size) {
595 while (size > 0) { 595 unsigned int order = fls(size >> PAGE_SHIFT)-1;
596 free_page((unsigned long) bh->b_data); 596
597 size -= PAGE_SIZE; 597 if (bh->b_data)
598 bh->b_data += PAGE_SIZE; 598 free_pages((unsigned long)bh->b_data, order);
599 } 599
600 size &= (order-1);
601 bh->b_data += (1 << order) * PAGE_SIZE;
600 } 602 }
601 prev_bh = bh; 603 prev_bh = bh;
602 bh = bh->b_reqnext; 604 bh = bh->b_reqnext;
@@ -1373,7 +1375,7 @@ static idetape_stage_t *ide_tape_kmalloc_buffer(idetape_tape_t *tape, int full,
1373 atomic_sub(tape->excess_bh_size, &bh->b_count); 1375 atomic_sub(tape->excess_bh_size, &bh->b_count);
1374 return stage; 1376 return stage;
1375abort: 1377abort:
1376 __idetape_kfree_stage(stage); 1378 ide_tape_kfree_buffer(stage);
1377 return NULL; 1379 return NULL;
1378} 1380}
1379 1381
@@ -1649,7 +1651,7 @@ static int __idetape_discard_read_pipeline(ide_drive_t *drive)
1649 clear_bit(IDETAPE_FLAG_FILEMARK, &tape->flags); 1651 clear_bit(IDETAPE_FLAG_FILEMARK, &tape->flags);
1650 tape->merge_stage_size = 0; 1652 tape->merge_stage_size = 0;
1651 if (tape->merge_stage != NULL) { 1653 if (tape->merge_stage != NULL) {
1652 __idetape_kfree_stage(tape->merge_stage); 1654 ide_tape_kfree_buffer(tape->merge_stage);
1653 tape->merge_stage = NULL; 1655 tape->merge_stage = NULL;
1654 } 1656 }
1655 1657
@@ -1828,7 +1830,7 @@ static void idetape_empty_write_pipeline(ide_drive_t *drive)
1828 tape->merge_stage_size = 0; 1830 tape->merge_stage_size = 0;
1829 } 1831 }
1830 if (tape->merge_stage != NULL) { 1832 if (tape->merge_stage != NULL) {
1831 __idetape_kfree_stage(tape->merge_stage); 1833 ide_tape_kfree_buffer(tape->merge_stage);
1832 tape->merge_stage = NULL; 1834 tape->merge_stage = NULL;
1833 } 1835 }
1834 tape->chrdev_dir = IDETAPE_DIR_NONE; 1836 tape->chrdev_dir = IDETAPE_DIR_NONE;
@@ -1866,7 +1868,7 @@ static int idetape_init_read(ide_drive_t *drive)
1866 REQ_IDETAPE_READ, 0, 1868 REQ_IDETAPE_READ, 0,
1867 tape->merge_stage->bh); 1869 tape->merge_stage->bh);
1868 if (bytes_read < 0) { 1870 if (bytes_read < 0) {
1869 __idetape_kfree_stage(tape->merge_stage); 1871 ide_tape_kfree_buffer(tape->merge_stage);
1870 tape->merge_stage = NULL; 1872 tape->merge_stage = NULL;
1871 tape->chrdev_dir = IDETAPE_DIR_NONE; 1873 tape->chrdev_dir = IDETAPE_DIR_NONE;
1872 return bytes_read; 1874 return bytes_read;
@@ -2145,7 +2147,7 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
2145 REQ_IDETAPE_WRITE, 0, 2147 REQ_IDETAPE_WRITE, 0,
2146 tape->merge_stage->bh); 2148 tape->merge_stage->bh);
2147 if (retval < 0) { 2149 if (retval < 0) {
2148 __idetape_kfree_stage(tape->merge_stage); 2150 ide_tape_kfree_buffer(tape->merge_stage);
2149 tape->merge_stage = NULL; 2151 tape->merge_stage = NULL;
2150 tape->chrdev_dir = IDETAPE_DIR_NONE; 2152 tape->chrdev_dir = IDETAPE_DIR_NONE;
2151 return retval; 2153 return retval;
@@ -2512,7 +2514,7 @@ static void idetape_write_release(ide_drive_t *drive, unsigned int minor)
2512 if (tape->merge_stage != NULL) { 2514 if (tape->merge_stage != NULL) {
2513 idetape_pad_zeros(drive, tape->blk_size * 2515 idetape_pad_zeros(drive, tape->blk_size *
2514 (tape->user_bs_factor - 1)); 2516 (tape->user_bs_factor - 1));
2515 __idetape_kfree_stage(tape->merge_stage); 2517 ide_tape_kfree_buffer(tape->merge_stage);
2516 tape->merge_stage = NULL; 2518 tape->merge_stage = NULL;
2517 } 2519 }
2518 idetape_write_filemark(drive); 2520 idetape_write_filemark(drive);