From e9bd25bff0453fa37fbeeba47cf28bc3324d4448 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Schmidt?= Date: Tue, 29 Nov 2005 20:08:26 +0000 Subject: [PATCH] Fix the ata_composite/ata_request leak when using RAID0+1. Submitted by: Michael Butler Minor changes to fit ATA style by me. --- sys/dev/ata/ata-all.h | 1 + sys/dev/ata/ata-raid.c | 26 +++++++++++++++++--------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h index 48d819ca5580..46f3c0a4d908 100644 --- a/sys/dev/ata/ata-all.h +++ b/sys/dev/ata/ata-all.h @@ -331,6 +331,7 @@ struct ata_composite { u_int32_t wr_depend; /* write depends on subdisks */ u_int32_t wr_done; /* done write subdisks */ struct ata_request *request[32]; /* size must match maps above */ + u_int32_t residual; /* bytes still to transfer */ caddr_t data_1; caddr_t data_2; }; diff --git a/sys/dev/ata/ata-raid.c b/sys/dev/ata/ata-raid.c index 6411c3c36962..e9d2f22080a5 100644 --- a/sys/dev/ata/ata-raid.c +++ b/sys/dev/ata/ata-raid.c @@ -405,6 +405,7 @@ ata_raid_strategy(struct bio *bp) mtx_init(&composite->lock, "ATA PseudoRAID rebuild lock", NULL, MTX_DEF); + composite->residual = request->bytecount; composite->rd_needed |= (1 << drv); composite->wr_depend |= (1 << drv); composite->wr_needed |= (1 << this); @@ -463,6 +464,7 @@ ata_raid_strategy(struct bio *bp) mtx_init(&composite->lock, "ATA PseudoRAID mirror lock", NULL, MTX_DEF); + composite->residual = request->bytecount; composite->wr_needed |= (1 << drv); composite->wr_needed |= (1 << this); composite->request[drv] = request; @@ -557,7 +559,7 @@ ata_raid_done(struct ata_request *request) } else { bp->bio_resid -= request->donecount; - if (bp->bio_resid == 0) + if (!bp->bio_resid) finished = 1; } break; @@ -602,7 +604,8 @@ ata_raid_done(struct ata_request *request) /* good data, update how far we've gotten */ else { bp->bio_resid -= request->donecount; - if (bp->bio_resid == 0) { + composite->residual -= request->donecount; + if (!composite->residual) { if (composite->wr_done & (1 << mirror)) finished = 1; } @@ -616,7 +619,7 @@ ata_raid_done(struct ata_request *request) printf("DOH! rebuild failed\n"); /* XXX SOS */ rdp->rebuild_lba = blk; } - if (bp->bio_resid == 0) + if (!composite->residual) finished = 1; } } @@ -633,7 +636,7 @@ ata_raid_done(struct ata_request *request) /* we have good data */ else { bp->bio_resid -= request->donecount; - if (bp->bio_resid == 0) + if (!bp->bio_resid) finished = 1; } } @@ -653,10 +656,14 @@ ata_raid_done(struct ata_request *request) } bp->bio_resid -= composite->request[mirror]->donecount; + composite->residual -= + composite->request[mirror]->donecount; } - else + else { bp->bio_resid -= request->donecount; - if (bp->bio_resid == 0) + composite->residual -= request->donecount; + } + if (!composite->residual) finished = 1; } mtx_unlock(&composite->lock); @@ -664,7 +671,7 @@ ata_raid_done(struct ata_request *request) /* no mirror we are done */ else { bp->bio_resid -= request->donecount; - if (bp->bio_resid == 0) + if (!bp->bio_resid) finished = 1; } } @@ -693,7 +700,7 @@ ata_raid_done(struct ata_request *request) else { // did we have an XOR game going ?? bp->bio_resid -= request->donecount; - if (bp->bio_resid == 0) + if (!bp->bio_resid) finished = 1; } break; @@ -718,7 +725,8 @@ ata_raid_done(struct ata_request *request) rdp->status &= ~AR_S_REBUILDING; ata_raid_config_changed(rdp, 1); } - biodone(bp); + if (!bp->bio_resid) + biodone(bp); } if (composite) {