From b39ce6cd6811cc2095fd2dabe82150da7168f800 Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Mon, 20 May 2013 03:18:55 +0400 Subject: [PATCH] Stupidly switch buffer --- sftl.c | 48 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/sftl.c b/sftl.c index cc94a73..11d5d94 100644 --- a/sftl.c +++ b/sftl.c @@ -91,6 +91,21 @@ static void sftl_complete_seg(struct bio *bio, int err) bio_put(bio); } +struct sftl_buf_info +{ + struct bio *complete_bio; + void *free_buf; +}; + +static void sftl_complete_buf(struct bio *bio, int err) +{ + struct sftl_buf_info *i = bio->bi_private; + bio_endio(i->complete_bio, err); + bio_put(bio); + kfree(i->free_buf); + kfree(i); +} + static void sftl_make_request(struct request_queue *q, struct bio *bio) { struct sftl_dev *sftl = (struct sftl_dev*)q->queuedata; @@ -151,20 +166,28 @@ static void sftl_make_request(struct request_queue *q, struct bio *bio) (unsigned long)bio->bi_sector, (unsigned long)bio_sectors(bio)); if (sftl->buf_size >= sftl->buf_max) { - // Need to flush the buffer before completing this bio - int err = bio_submit_kern_seq(sftl->blkdev, sftl->buf, seg_clust*clust_sz+phy_sz, GFP_KERNEL, - sftl->nextfreeseg*(seg_clust*clust_blocks+1), bio, sftl_complete_seg, WRITE); - if (err) - bio_endio(bio, -EIO); - // FIXME Is it correct?.. I think no... + // Need to flush current buffer before completing this bio + void *buf = sftl->buf; + struct sftl_buf_info *info = kmalloc(sizeof(struct sftl_buf_info), GFP_KERNEL); + int err; + info->free_buf = buf; + info->complete_bio = bio; + // We stupidly switch buffer (there always will be a finite number of those) + sftl->buf = kmalloc(seg_clust*clust_sz + phy_sz, GFP_KERNEL); sftl->buf_size = 0; + err = bio_submit_kern_seq(sftl->blkdev, buf, seg_clust*clust_sz+phy_sz, GFP_KERNEL, + sftl->nextfreeseg*(seg_clust*clust_blocks+1), info, sftl_complete_buf, WRITE); + if (err) + { + bio_endio(bio, -EIO); + kfree(buf); + kfree(info); + } // FIXME Correctly adjust free segment address sftl->nextfreeseg++; } else - { bio_endio(bio, 0); - } } } @@ -318,7 +341,7 @@ static void bio_map_kern_seq_endio(struct bio *bio, int err) struct bio_seq *seq = bio->bi_private; if (err) { - INFO("I/O err %d", err); + INFO("I/O error %d", err); seq->err = err; } if (atomic_dec_and_test(&seq->count)) @@ -362,6 +385,7 @@ static long bio_submit_kern_seq( int n = 1; bio->bi_private = NULL; bio->bi_end_io = bio_map_kern_seq_endio; + seq->err = 0; seq->endio = endio; seq->private = private; data += bio->bi_size; @@ -382,13 +406,13 @@ static long bio_submit_kern_seq( } return PTR_ERR(bio2); } - data += bio2->bi_size; - len -= bio2->bi_size; - sector += bio2->bi_size >> 9; bio2->bi_bdev = bdev; bio2->bi_sector = sector; bio2->bi_private = bio; bio2->bi_end_io = bio_map_kern_seq_endio; + data += bio2->bi_size; + len -= bio2->bi_size; + sector += bio2->bi_size >> 9; bio = bio2; n++; }