diff --git a/dm-compress/compress.c b/dm-compress/compress.c index 969d126..5ed274b 100644 --- a/dm-compress/compress.c +++ b/dm-compress/compress.c @@ -91,7 +91,8 @@ compress_read_header(struct compress* c) pblkbuf = page_address(pblkpage); iopagev[0] = pblkpage; - ret = pblk_read_wait(c->dev->bdev, 0, 1, iopagev); + header.params.priv = c->dev->bdev; + ret = pblk_read_wait(&header.params, 0, 1, iopagev); if (ret) { printk(KERN_ERR "%s: failed to read header\n", __func__); goto out; @@ -186,7 +187,7 @@ compress_write_header(struct compress* c) memcpy(&header.stats, &c->stats, sizeof(header.stats)); cbd_header_put(pblkbuf, &header); iopagev[0] = pblkpage; - ret = pblk_write_wait(c->params.priv, 0, 1, iopagev); + ret = pblk_write_wait(&c->params, 0, 1, iopagev); if (ret) { printk(KERN_ERR "%s: failed to write header\n", __func__); } @@ -475,6 +476,12 @@ compress_map(struct dm_target *ti, struct bio *bio) struct compress *c = ti->private; struct compress_io *cio; + if (c->params.flags & CBD_FLAG_ERROR) { + bio->bi_status = BLK_STS_IOERR; + bio_endio(bio); + return DM_MAPIO_SUBMITTED; /* XXXX: DM_MAPIO_KILL? */ + } + /* from dm-crypt.c */ if (unlikely(bio->bi_opf & REQ_PREFLUSH || bio_op(bio) == REQ_OP_DISCARD)) { bio_set_dev(bio, c->dev->bdev); diff --git a/dm-compress/lbatpage.c b/dm-compress/lbatpage.c index 97001e2..c96a1a0 100644 --- a/dm-compress/lbatpage.c +++ b/dm-compress/lbatpage.c @@ -91,7 +91,7 @@ lbatpage_flush(struct lbatpage* lp) goto unlock; } iopagev[0] = lp->page; - pblk_write(lp->params->priv, lp->pblk, 1, iopagev); + pblk_write(lp->params, lp->pblk, 1, iopagev); mutex_unlock(&lp->lock); return ret; @@ -110,7 +110,7 @@ lbatpage_read(struct lbatpage* lp) struct page* pagev[1]; pagev[0] = lp->page; - ret = pblk_read_wait(lp->params->priv, lp->pblk, 1, pagev); + ret = pblk_read_wait(lp->params, lp->pblk, 1, pagev); return ret; } diff --git a/dm-compress/lbd.c b/dm-compress/lbd.c index aa1f648..3039f93 100644 --- a/dm-compress/lbd.c +++ b/dm-compress/lbd.c @@ -354,7 +354,7 @@ lbd_flush(struct lbd* lbd, struct cbd_stats* stats) pblk = lbatview_elem_pblk(lbd->lv, lbd->lblk, n); BUG_ON(pblk == PBLK_NONE); iopagev[0] = lbd->pagev[n]; - pblk_write(lbd->params->priv, pblk, 1, iopagev); + pblk_write(lbd->params, pblk, 1, iopagev); } while (n < lblk_per_pblk(lbd->params)) { unlock_page(lbd->pagev[n]); @@ -407,7 +407,7 @@ lbd_read(struct lbd* lbd) } iopagev[0] = lbd->pagev[n]; /* XXX: Issue non-blocking reads? */ - ret = pblk_read_wait(lbd->params->priv, pblk, 1, iopagev); + ret = pblk_read_wait(lbd->params, pblk, 1, iopagev); if (ret) { goto out; } diff --git a/dm-compress/pbat.c b/dm-compress/pbat.c index af45688..eaa5510 100644 --- a/dm-compress/pbat.c +++ b/dm-compress/pbat.c @@ -112,7 +112,7 @@ pbat_flush(struct pbat* pbat) goto unlock; } pblk = pbat_off(pbat->params, pbat->zone); - pblk_write(pbat->params->priv, pblk, nr_pages, pbat->pagev); + pblk_write(pbat->params, pblk, nr_pages, pbat->pagev); mutex_unlock(&pbat->lock); return ret; @@ -138,7 +138,7 @@ pbat_read(struct pbat* pbat) return -EIO; } pblk = pbat_off(pbat->params, pbat->zone); - ret = pblk_read_wait(pbat->params->priv, pblk, nr_pages, pbat->pagev); + ret = pblk_read_wait(pbat->params, pblk, nr_pages, pbat->pagev); return ret; } diff --git a/dm-compress/util.c b/dm-compress/util.c index 0f3a16e..1b242b2 100644 --- a/dm-compress/util.c +++ b/dm-compress/util.c @@ -123,13 +123,13 @@ pblk_io_prepare(struct block_device* bdev, unsigned int op, } int -pblk_read_wait(struct block_device* bdev, +pblk_read_wait(struct cbd_params* params, u64 pblk, u32 count, struct page** pagev) { int ret; struct bio* bio; - bio = pblk_io_prepare(bdev, REQ_OP_READ, pblk, count, pagev); + bio = pblk_io_prepare(params->priv, REQ_OP_READ, pblk, count, pagev); if (!bio) { printk(KERN_ERR "%s: out of memory\n", __func__); return -ENOMEM; @@ -144,13 +144,13 @@ pblk_read_wait(struct block_device* bdev, } int -pblk_write_wait(struct block_device* bdev, +pblk_write_wait(struct cbd_params* params, u64 pblk, u32 count, struct page** pagev) { int ret; struct bio* bio; - bio = pblk_io_prepare(bdev, REQ_OP_WRITE, pblk, count, pagev); + bio = pblk_io_prepare(params->priv, REQ_OP_WRITE, pblk, count, pagev); if (!bio) { printk(KERN_ERR "%s: out of memory\n", __func__); return -ENOMEM; @@ -158,6 +158,7 @@ pblk_write_wait(struct block_device* bdev, ret = submit_bio_wait(bio); if (ret) { printk(KERN_ERR "%s: submit_bio_wait failed: %d\n", __func__, ret); + params->flags |= CBD_FLAG_ERROR; } bio_put(bio); @@ -167,11 +168,13 @@ pblk_write_wait(struct block_device* bdev, void pblk_write_endio(struct bio* bio) { + struct cbd_params* params = bio->bi_private; u32 n; struct page* page; BUG_ON(!bio); if (bio->bi_status != BLK_STS_OK) { + params->flags |= CBD_FLAG_ERROR; for (n = 0; n < bio->bi_max_vecs; ++n) { page = bio->bi_io_vec[n].bv_page; SetPageError(page); @@ -186,15 +189,16 @@ pblk_write_endio(struct bio* bio) } void -pblk_write(struct block_device* bdev, +pblk_write(struct cbd_params* params, u64 pblk, u32 count, struct page** pagev) { struct bio* bio; u32 n; - bio = pblk_io_prepare(bdev, REQ_OP_WRITE, pblk, count, pagev); + bio = pblk_io_prepare(params->priv, REQ_OP_WRITE, pblk, count, pagev); if (!bio) { printk(KERN_ERR "%s: out of memory\n", __func__); + params->flags |= CBD_FLAG_ERROR; for (n = 0; n < count; ++n) { SetPageError(pagev[n]); unlock_page(pagev[n]); @@ -202,6 +206,7 @@ pblk_write(struct block_device* bdev, return; } bio->bi_end_io = pblk_write_endio; + bio->bi_private = params; submit_bio(bio); } diff --git a/include/linux/dm-compress.h b/include/linux/dm-compress.h index 156ea3c..fd71080 100644 --- a/include/linux/dm-compress.h +++ b/include/linux/dm-compress.h @@ -29,6 +29,7 @@ static const u16 CBD_VERSION_MAJOR = 1; static const u16 CBD_VERSION_MINOR = 1; #define CBD_FLAG_DIRTY 0x01 +#define CBD_FLAG_ERROR 0x02 enum cbd_alg { CBD_ALG_NONE, @@ -523,11 +524,11 @@ bool cbd_alloc_pagev(struct page** pagev, size_t len); void cbd_free_pagev(struct page** pagev, size_t len); /* Core low-level I/O */ -int pblk_read_wait(struct block_device* bdev, +int pblk_read_wait(struct cbd_params* params, u64 pblk, u32 count, struct page** pagev); -int pblk_write_wait(struct block_device* bdev, +int pblk_write_wait(struct cbd_params* params, u64 pblk, u32 count, struct page** pagev); -void pblk_write(struct block_device* bdev, +void pblk_write(struct cbd_params* params, u64 pblk, u32 count, struct page** pagev); struct pbat;