diff --git a/dm-compress/compress.c b/dm-compress/compress.c index aba2db9..a69ce65 100644 --- a/dm-compress/compress.c +++ b/dm-compress/compress.c @@ -56,7 +56,6 @@ struct compress struct lbdcache* lc; struct workqueue_struct* io_workq; - bool io_failed; }; static inline u64 @@ -76,14 +75,13 @@ dm_target_pblk_size(struct dm_target* ti) **************************************/ static int -compress_open(struct compress* c, u64 dev_nr_pblks) +compress_read_header(struct compress* c) { - int err; + int ret = 0; struct page* pblkpage; u8 *pblkbuf; struct page* iopagev[1]; struct cbd_header header; - u64 max_nr_zones; pblkpage = cbd_alloc_page(); if (!pblkpage) { @@ -94,76 +92,59 @@ compress_open(struct compress* c, u64 dev_nr_pblks) memset(&header, 0, sizeof(header)); header.params.priv = c->dev->bdev; - err = pblk_read_wait(&header.params, 0, 1, iopagev); - if (err) { + ret = pblk_read_wait(&header.params, 0, 1, iopagev); + if (ret) { printk(KERN_ERR "%s: failed to read header\n", __func__); - cbd_free_page(pblkpage); - return err; + goto out; } cbd_header_get(pblkbuf, &header); - cbd_free_page(pblkpage); if (memcmp(header.magic, CBD_MAGIC, sizeof(header.magic)) != 0) { printk(KERN_ERR "%s: bad magic\n", __func__); - err = -EINVAL; + ret = -EINVAL; goto out; } if (header.version_major != CBD_VERSION_MAJOR) { printk(KERN_ERR "%s: bad version\n", __func__); - err = -EINVAL; + ret = -EINVAL; goto out; } if (header.version_minor != CBD_VERSION_MINOR) { printk(KERN_ERR "%s: bad version\n", __func__); - err = -EINVAL; + ret = -EINVAL; goto out; } if (header.params.algorithm == CBD_ALG_NONE || header.params.algorithm >= CBD_ALG_MAX) { printk(KERN_ERR "%s: bad algorithm\n", __func__); - err = -EINVAL; + ret = -EINVAL; goto out; } #ifndef COMPRESS_HAVE_LZ4 if (header.params.algorithm == CBD_ALG_LZ4) { printk(KERN_ERR "%s: algorithm lz4 is not built into kernel\n", __func__); - err = -EINVAL; + ret = -EINVAL; goto out; } #endif #ifndef COMPRESS_HAVE_ZLIB if (header.params.algorithm == CBD_ALG_ZLIB) { printk(KERN_ERR "%s: algorithm zlib is not built into kernel\n", __func__); - err = -EINVAL; + ret = -EINVAL; goto out; } #endif if (header.params.compression < 1 || header.params.compression > 9) { printk(KERN_ERR "%s: bad compression\n", __func__); - err = -EINVAL; + ret = -EINVAL; goto out; } if (header.params.lblk_shift < LBLK_SHIFT_MIN || header.params.lblk_shift > LBLK_SHIFT_MAX) { printk(KERN_ERR "%s: bad lblk_shift\n", __func__); - err = -EINVAL; + ret = -EINVAL; goto out; } - /* XXX: validate minumum pblk using zone_off(max_zone+1) */ - if (header.params.nr_pblk > dev_nr_pblks) { - printk(KERN_ERR "%s: bad nr_pblk\n", __func__); - err = -EINVAL; - goto out; - } - - max_nr_zones = zone_for_pblk(&header.params, dev_nr_pblks); - if (header.params.nr_zones > max_nr_zones) { - printk(KERN_ERR "%s: bad nr_zones\n", __func__); - err = -EINVAL; - goto out; - } - - /* XXX: validate lblk_per_zone */ printk(KERN_INFO "%s: parameters...\n", __func__); printk(KERN_INFO " algorithm=%hu\n", (unsigned short)header.params.algorithm); @@ -175,30 +156,9 @@ compress_open(struct compress* c, u64 dev_nr_pblks) memcpy(&c->params, &header.params, sizeof(header.params)); - c->lc = kmalloc(lbdcache_size(), GFP_KERNEL); - if (!c->lc) { - err = -ENOMEM; - printk(KERN_ERR "Failed to alloc lbdcache\n"); - goto out; - } - if (!lbdcache_ctr(c->lc, &c->params)) { - err = -ENOMEM; - printk(KERN_ERR "Failed to init logical block cache\n"); - goto out; - } - - c->io_workq = alloc_workqueue("compress_io", WQ_HIGHPRI | WQ_MEM_RECLAIM, 1); - if (!c->io_workq) { - printk(KERN_ERR "%s: failed to alloc io_workq\n", __func__); - err = -ENOMEM; - goto out; - } - c->io_failed = false; - out: - /* XXX: cleanup on error */ - - return err; + cbd_free_page(pblkpage); + return ret; } static struct lbd* @@ -340,7 +300,7 @@ compress_io_work(struct work_struct* work) static int compress_ctr(struct dm_target *ti, unsigned int argc, char **argv) { - int err; + int ret; unsigned int argn; struct compress *c = NULL; u64 dev_nr_pblks; @@ -394,22 +354,59 @@ compress_ctr(struct dm_target *ti, unsigned int argc, char **argv) if (get_order(dev_nr_pblks) >= 48) { ti->error = "Device too large"; - kfree(c); - return -EINVAL; + ret = -EINVAL; + goto err; } ti->per_io_data_size = ALIGN(sizeof(struct compress_io), ARCH_KMALLOC_MINALIGN); - err = compress_open(c, dev_nr_pblks); - if (err) { - dm_put_device(ti, c->dev); - kfree(c); - return err; + ret = compress_read_header(c); + if (ret) { + goto err; + } + + /* XXX: validate minumum pblk using zone_off(max_zone+1) */ + if (c->params.nr_pblk > dev_nr_pblks) { + printk(KERN_ERR "%s: bad nr_pblk\n", __func__); + ret = -EINVAL; + goto err; + } + + if (c->params.nr_zones > zone_for_pblk(&c->params, dev_nr_pblks)) { + printk(KERN_ERR "%s: bad nr_zones\n", __func__); + ret = -EINVAL; + goto err; + } + + /* XXX: validate lblk_per_zone */ + + c->lc = kmalloc(lbdcache_size(), GFP_KERNEL); + if (!c->lc) { + printk(KERN_ERR "Failed to alloc lbdcache\n"); + ret = -ENOMEM; + goto err; + } + if (!lbdcache_ctr(c->lc, &c->params)) { + printk(KERN_ERR "Failed to init logical block cache\n"); + ret = -ENOMEM; + goto err; + } + + c->io_workq = alloc_workqueue("compress_io", WQ_HIGHPRI | WQ_MEM_RECLAIM, 1); + if (!c->io_workq) { + printk(KERN_ERR "%s: failed to alloc io_workq\n", __func__); + ret = -ENOMEM; + goto err; } printk(KERN_INFO "%s: success\n", __func__); return 0; + +err: + dm_put_device(ti, c->dev); + kfree(c); + return ret; } static void @@ -435,10 +432,6 @@ compress_map(struct dm_target *ti, struct bio *bio) struct compress *c = ti->private; struct compress_io *cio; - if (c->io_failed) { - return 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);