Stupidly switch buffer

master
Vitaliy Filippov 2013-05-20 03:18:55 +04:00
parent b814b86302
commit b39ce6cd68
1 changed files with 36 additions and 12 deletions

48
sftl.c
View File

@ -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++;
}