From 07f4221a5f5a714abd886f9c9c49cd7486f9b26a Mon Sep 17 00:00:00 2001
From: Tom Marshall <tdm.code@gmail.com>
Date: Thu, 10 Oct 2019 13:21:36 -0700
Subject: [PATCH] Fix a bunch of things

* Fix command line handling.
* Move option/parameter validation to libcbd.
* Make resize argument the logical size.
* Make blkdev_pblk_* take dm_compress instead of block_device.
* Reinstate dm_compress.io_failed.
* Other misc stuff.
---
 cbd/cbd.c                   | 115 +++++++++++++++---------------------
 dm-compress/dm-compress.c   |  40 +++++++------
 include/libcbd.h            |   9 ++-
 include/linux/dm-compress.h |   3 +
 libcbd/check.c              |   8 +--
 libcbd/format.c             |  53 ++++++++++-------
 libcbd/open.c               |  26 ++++----
 libcbd/resize.c             |   2 +-
 8 files changed, 130 insertions(+), 126 deletions(-)

diff --git a/cbd/cbd.c b/cbd/cbd.c
index aa0f80f..f0b47c3 100644
--- a/cbd/cbd.c
+++ b/cbd/cbd.c
@@ -84,7 +84,6 @@ usage(void)
     fprintf(stderr, "Commands:\n"
                     "  format [opts] <device>          Create (format) a compressed device\n"
                     "    -S      --pysical-size          Physical size [device size]\n"
-                    "    -O      --offset                Offset in device [0]\n"
                     "    -L      --logical-blksize       Logical block size\n"
                     "    -c      --compress-factor       Compression factor [2.0]\n"
                     "    -l      --logical-shift         Logical block shift [4]\n"
@@ -102,7 +101,7 @@ usage(void)
                     "    -n      --assume-no             Assume \"no\" no all questions\n"
                     "    -y      --assume-yes            Assume \"yes\" to all questions\n"
                     "  resize [opts] <device>          Resize an existing compressed device\n"
-                    "    -S      --physical-size         New (physical) size [use all]\n"
+                    "    -s      --size                New logical size [use all]\n"
                     "  stats [opts] <name>             Show device statistics\n"
                     "\n");
     exit(1);
@@ -111,22 +110,20 @@ usage(void)
 static int
 do_format(int argc, char** argv)
 {
-    static const char short_opts[] = "S:O:L:c:l:s:";
+    static const char short_opts[] = "S:L:c:l:s:";
     static const struct option long_opts[] = {
-        { "physical-size",   1, NULL, 'S' },
-        { "offset",          1, NULL, 'O' },
-        { "logical-blksize", 1, NULL, 'L' },
-        { "compress-factor", 1, NULL, 'c' },
-        { "logical-shift",   1, NULL, 'l' },
-        { "size",            1, NULL, 's' },
-        { NULL,              0, NULL, 0   }
+        { "physical-size",   required_argument, NULL, 'S' },
+        { "logical-blksize", required_argument, NULL, 'L' },
+        { "compress-factor", required_argument, NULL, 'c' },
+        { "logical-shift",   required_argument, NULL, 'l' },
+        { "size",            required_argument, NULL, 's' },
+        { NULL,              no_argument,       NULL, 0   }
     };
     char opt;
     uint64_t optval;
-    uint64_t poff = 0;
     uint64_t psize = 0;
-    uint64_t lsize = 0;
     uint16_t lshift = 0;
+    uint64_t lsize = 0;
 
     const char* dev;
 
@@ -137,23 +134,12 @@ do_format(int argc, char** argv)
                 error("Failed to parse \"%s\"\n", optarg);
             }
             psize = optval;
-            if (psize % PBLK_SIZE) {
-                error("Size \"%s\" is not a multiple of %u bytes\n", optarg, (uint)PBLK_SIZE);
-            }
-            break;
-        case 'O':
-            if (!parse_arg(optarg, &optval)) {
-                error("Failed to parse \"%s\"\n", optarg);
-            }
-            poff = optval;
             break;
         case 'L':
             if (!parse_arg(optarg, &optval)) {
                 error("Failed to parse \"%s\"\n", optarg);
             }
-            if ((optval & (optval-1)) ||
-                 optval < (1 << (PBLK_SHIFT + LBLK_SHIFT_MIN)) ||
-                 optval > (1 << (PBLK_SHIFT + LBLK_SHIFT_MAX))) {
+            if ((optval & (optval-1)) || optval < PBLK_SIZE) {
                 error("Size \"%s\" is not a valid logical block size\n", optarg);
             }
             lshift = (optval >> PBLK_SHIFT);
@@ -165,9 +151,6 @@ do_format(int argc, char** argv)
             if (!parse_arg(optarg, &optval)) {
                 error("Failed to parse \"%s\"\n", optarg);
             }
-            if (optval < LBLK_SHIFT_MIN || optval > LBLK_SHIFT_MAX) {
-                error("Size \"%s\" is not a valid logical block shift\n", optarg);
-            }
             lshift = optval;
             break;
         case 's':
@@ -175,9 +158,6 @@ do_format(int argc, char** argv)
                 error("Failed to parse \"%s\"\n", optarg);
             }
             lsize = optval;
-            if (lsize % PBLK_SIZE) {
-                error("Size \"%s\" is not a multiple of %u bytes\n", optarg, (uint)PBLK_SIZE);
-            }
             break;
         default:
             usage();
@@ -188,7 +168,7 @@ do_format(int argc, char** argv)
     }
     dev = argv[optind++];
 
-    cbd_format(dev, poff, psize, lsize, lshift);
+    cbd_format(dev, psize, lshift, lsize);
 
     return 0;
 }
@@ -197,19 +177,18 @@ static int
 do_open(int argc, char** argv)
 {
     char dev[PATH_MAX];
-    char name[PATH_MAX];
+    const char* name;
 
     if (argc != 3) {
         usage();
     }
     strcpy(dev, argv[1]);
-    strcpy(name, argv[2]);
-
     if (dev[0] != '/') {
         sprintf(dev, "/dev/mapper/%s", argv[1]);
     }
+    name = argv[2];
 
-    cbd_open(dev, 0, 0, name);
+    cbd_open(dev, name);
 
     return 0;
 }
@@ -229,14 +208,29 @@ do_close(int argc, char** argv)
     return 0;
 }
 
+static int
+do_stats(int argc, char** argv)
+{
+    const char* name;
+
+    if (argc != 2) {
+        usage();
+    }
+    name = argv[1];
+
+    cbd_stats(name);
+
+    return 0;
+}
+
 static int
 do_check(int argc, char** argv)
 {
     static const char short_opts[] = "ny";
     static const struct option long_opts[] = {
-        { "assume-no",  0, NULL, 'n' },
-        { "assume-yes", 0, NULL, 'y' },
-        { NULL,         0, NULL, 0   }
+        { "assume-no",  no_argument,       NULL, 'n' },
+        { "assume-yes", no_argument,       NULL, 'y' },
+        { NULL,         no_argument,       NULL, 0   }
     };
     char opt;
     tristate_t auto_response = t_none;
@@ -276,27 +270,25 @@ do_check(int argc, char** argv)
 static int
 do_resize(int argc, char** argv)
 {
-    static const char short_opts[] = "S:";
+    static const char short_opts[] = "s:";
     static const struct option long_opts[] = {
-        { "physical-size", 1, NULL, 'S' },
-        { NULL,            0, NULL, 0   }
+        { "size",   required_argument, NULL, 's' },
+        { NULL,     no_argument,       NULL, 0   }
     };
     char opt;
-    uint64_t poff = 0;
-    uint64_t psize = 0;
+    uint64_t optval;
+    uint64_t lsize = 0;
 
-    const char* dev;
+    char dev[PATH_MAX];
 
     while ((opt = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
         switch (opt) {
-        case 'S':
-            if (!parse_arg(optarg, &psize)) {
+        case 's':
+            if (!parse_arg(optarg, &optval)) {
                 fprintf(stderr, "Failed to parse \"%s\"\n", optarg);
                 usage();
             }
-            if (psize % PBLK_SIZE) {
-                fprintf(stderr, "Size \"%s\" is not a multiple of %u bytes\n", optarg, (uint)PBLK_SIZE);
-            }
+            lsize = optval;
             break;
         default:
             usage();
@@ -305,24 +297,13 @@ do_resize(int argc, char** argv)
     if (argc - optind != 1) {
         usage();
     }
-    dev = argv[optind++];
-
-    cbd_resize(dev, poff, psize / PBLK_SHIFT);
-
-    return 0;
-}
-
-static int
-do_stats(int argc, char** argv)
-{
-    const char* dev;
-
-    if (argc != 1) {
-        usage();
+    strcpy(dev, argv[optind]);
+    if (dev[0] != '/') {
+        sprintf(dev, "/dev/mapper/%s", argv[optind]);
     }
-    dev = argv[0];
+    ++optind;
 
-    cbd_stats(dev);
+    cbd_resize(dev, lsize);
 
     return 0;
 }
@@ -339,15 +320,15 @@ static struct cmd_dispatch dispatch[] =
     { "open",   do_open },
     { "create", do_open },
     { "close",  do_close },
+    { "stats",  do_stats },
     { "check",  do_check },
     { "resize", do_resize },
-    { "stats",  do_stats },
 };
 
 int
 main(int argc, char** argv)
 {
-    static const char short_opts[] = "v";
+    static const char short_opts[] = "+v";
     static const struct option long_opts[] = {
         { "verbose", 0, NULL, 'v' },
         { NULL,      0, NULL, 0   }
diff --git a/dm-compress/dm-compress.c b/dm-compress/dm-compress.c
index e5cea1a..bf2c011 100644
--- a/dm-compress/dm-compress.c
+++ b/dm-compress/dm-compress.c
@@ -53,12 +53,10 @@ struct dm_compress_io {
 struct dm_compress
 {
     struct dm_dev*              dev;
+    bool                        io_failed;
 
     struct cbd_params           params;
 
-    /* XXX: dm_target.off */
-    sector_t                    dm_off;
-
     u8*                         lz4_wrkmem;
     u8*                         lz4_cbuf;
 
@@ -170,7 +168,7 @@ compress_free_pages(void* ptr, size_t size)
  **************************************/
 
 static struct bio*
-blkdev_pblk_io_prepare(struct block_device* dev, unsigned int op, u64 pblk, u32 count, void *data)
+blkdev_pblk_io_prepare(struct dm_compress* dc, unsigned int op, u64 pblk, u32 count, void *data)
 {
     unsigned long data_addr;
     struct bio* bio;
@@ -184,7 +182,7 @@ blkdev_pblk_io_prepare(struct block_device* dev, unsigned int op, u64 pblk, u32
         printk(KERN_ERR "%s: out of memory\n", __func__);
         return NULL;
     }
-    bio_set_dev(bio, dev);
+    bio_set_dev(bio, dc->dev->bdev);
     bio->bi_opf = op;
 
     bio->bi_iter.bi_sector = (pblk << (PBLK_SHIFT - SECTOR_SHIFT));
@@ -200,12 +198,12 @@ blkdev_pblk_io_prepare(struct block_device* dev, unsigned int op, u64 pblk, u32
 }
 
 static int
-blkdev_pblk_read(struct block_device* dev, u64 pblk, u32 count, void *data)
+blkdev_pblk_read(struct dm_compress* dc, u64 pblk, u32 count, void *data)
 {
     int ret;
     struct bio* bio;
 
-    bio = blkdev_pblk_io_prepare(dev, REQ_OP_READ, pblk, count, data);
+    bio = blkdev_pblk_io_prepare(dc, REQ_OP_READ, pblk, count, data);
     if (!bio) {
         printk(KERN_ERR "%s: out of memory\n", __func__);
         return -ENOMEM;
@@ -226,20 +224,25 @@ blkdev_pblk_write_endio(struct bio* bio)
     void* data = page_address(bio->bi_io_vec[0].bv_page);
     unsigned int count = bio->bi_max_vecs;
     compress_free_pages(data, count);
+    if (bio->bi_status != BLK_STS_OK) {
+        struct dm_compress* dc = bio->bi_private;
+        dc->io_failed = true;
+    }
     bio_put(bio);
 }
 
 static void
-blkdev_pblk_write(struct block_device* dev, u64 pblk, u32 count, void *data)
+blkdev_pblk_write(struct dm_compress* dc, u64 pblk, u32 count, void *data)
 {
     struct bio* bio;
 
-    bio = blkdev_pblk_io_prepare(dev, REQ_OP_WRITE, pblk, count, data);
+    bio = blkdev_pblk_io_prepare(dc, REQ_OP_WRITE, pblk, count, data);
     if (!bio) {
         printk(KERN_ERR "%s: out of memory\n", __func__);
         return;
     }
     bio->bi_end_io = blkdev_pblk_write_endio;
+    bio->bi_private = dc;
 
     submit_bio(bio);
 }
@@ -264,7 +267,7 @@ pblk_alloc_write(struct dm_compress* dc)
         return -ENOMEM;
     }
     memcpy(pg, dc->pblk_alloc, count * PBLK_SIZE);
-    blkdev_pblk_write(dc->dev->bdev, pblk, count, pg);
+    blkdev_pblk_write(dc, pblk, count, pg);
 
     dc->pblk_alloc_dirty = false;
 
@@ -305,7 +308,7 @@ pblk_alloc_read(struct dm_compress* dc, u32 idx)
     pblk = pblk_alloc_off(&dc->params, idx);
     count = pblk_alloc_len(&dc->params);
 
-    ret = blkdev_pblk_read(dc->dev->bdev, pblk, count, dc->pblk_alloc);
+    ret = blkdev_pblk_read(dc, pblk, count, dc->pblk_alloc);
     if (ret) {
         return ret;
     }
@@ -425,7 +428,7 @@ lblk_alloc_elem_write(struct dm_compress* dc)
         return -ENOMEM;
     }
     memcpy(pg, dc->lblk_alloc, count * PBLK_SIZE);
-    blkdev_pblk_write(dc->dev->bdev, pblk, count, pg);
+    blkdev_pblk_write(dc, pblk, count, pg);
 
     return 0;
 }
@@ -455,7 +458,7 @@ lblk_alloc_elem_read(struct dm_compress* dc, u64 lblk)
     count = 1 + (elem_end - 1) / PBLK_SIZE - (elem_off / PBLK_SIZE);
     pblk = lblk_alloc_off(&dc->params, zone) + rel_pblk;
     if (dc->lblk_alloc_pblk != pblk || dc->lblk_alloc_len < count) {
-        ret = blkdev_pblk_read(dc->dev->bdev, pblk, count, dc->lblk_alloc);
+        ret = blkdev_pblk_read(dc, pblk, count, dc->lblk_alloc);
         if (ret != 0) {
             return ret;
         }
@@ -581,7 +584,7 @@ lblk_write(struct dm_compress* dc)
                 return -ENOMEM;
             }
             memcpy(pg, c_buf, PBLK_SIZE);
-            blkdev_pblk_write(dc->dev->bdev, pblk, 1, pg);
+            blkdev_pblk_write(dc, pblk, 1, pg);
             c_buf += PBLK_SIZE;
         }
         else {
@@ -674,7 +677,7 @@ lblk_read(struct dm_compress* dc, u64 idx)
         for (n = 0; n * PBLK_SIZE < c_len; ++n, p += PBLK_SIZE) {
             pblk = dc->lblk_alloc_elem->pblk[n];
             BUG_ON(pblk == 0);
-            ret = blkdev_pblk_read(dc->dev->bdev, pblk, 1, p);
+            ret = blkdev_pblk_read(dc, pblk, 1, p);
             if (ret != 0) {
                 return ret;
             }
@@ -787,7 +790,7 @@ compress_open(struct dm_compress* dc, u64 dev_nr_pblks)
         return -ENOMEM;
     }
 
-    err = blkdev_pblk_read(dc->dev->bdev, 0, 1, pblkbuf);
+    err = blkdev_pblk_read(dc, 0, 1, pblkbuf);
     if (err) {
         printk(KERN_ERR "%s: failed to read header\n", __func__);
         goto out;
@@ -1040,7 +1043,6 @@ compress_ctr(struct dm_target *ti, unsigned int argc, char **argv)
         kfree(dc);
         return -EINVAL;
     }
-    dc->dm_off = ti->begin;
 
     ti->private = dc;
 
@@ -1088,6 +1090,10 @@ compress_map(struct dm_target *ti, struct bio *bio)
     struct dm_compress *dc = (struct dm_compress *)ti->private;
     struct dm_compress_io *io;
 
+    if (dc->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, dc->dev->bdev);
diff --git a/include/libcbd.h b/include/libcbd.h
index b782978..ae2efe5 100644
--- a/include/libcbd.h
+++ b/include/libcbd.h
@@ -50,17 +50,16 @@ typedef enum {
 } tristate_t;
 
 int  cbd_format(const char* dev,
-                uint64_t poff, uint64_t psize,
-                uint64_t lsize, uint16_t lshift);
+                uint64_t psize, uint16_t lshift, uint64_t lsize);
 int  cbd_open(const char* dev,
-              uint64_t loff, uint64_t lsize,
               const char* name);
 int  cbd_close(const char* name);
 
 int  cbd_stats(const char* name);
 
-int  cbd_check(const char* dev, tristate_t auto_response);
+int  cbd_check(const char* dev,
+               tristate_t auto_response);
 int  cbd_resize(const char* dev,
-                uint64_t poff, uint64_t psize);
+                uint64_t lsize);
 
 #endif
diff --git a/include/linux/dm-compress.h b/include/linux/dm-compress.h
index 0295be0..2608281 100644
--- a/include/linux/dm-compress.h
+++ b/include/linux/dm-compress.h
@@ -4,6 +4,9 @@
 #ifndef SECTOR_SHIFT
 #define SECTOR_SHIFT 9
 #endif
+#ifndef SECTOR_SIZE
+#define SECTOR_SIZE (1 << SECTOR_SHIFT)
+#endif
 
 #define PBLK_SHIFT 12
 #define PBLK_SIZE (1 << PBLK_SHIFT)
diff --git a/libcbd/check.c b/libcbd/check.c
index 89b669c..01fac80 100644
--- a/libcbd/check.c
+++ b/libcbd/check.c
@@ -9,14 +9,14 @@ struct zone_metadata
 };
 
 static void
-pblk_read(int fd, size_t pblk, size_t count, u8* data)
+pblk_read(int fd, u64 pblk, u32 count, u8* data)
 {
-    off_t off;
+    off_t pos;
     size_t remain;
     ssize_t ret;
 
-    off = lseek(fd, pblk * PBLK_SIZE, SEEK_SET);
-    if (off == (off_t)-1) {
+    pos = lseek(fd, pblk * PBLK_SIZE, SEEK_SET);
+    if (pos == (off_t)-1) {
         error("Failed to seek\n");
     }
 
diff --git a/libcbd/format.c b/libcbd/format.c
index a8b4b34..16dc430 100644
--- a/libcbd/format.c
+++ b/libcbd/format.c
@@ -3,14 +3,14 @@
 #include <cbdutil.h>
 
 static void
-pblk_write(int fd, size_t pblk, size_t count, const u8* data)
+pblk_write(int fd, u64 pblk, u32 count, const u8* data)
 {
-    off_t off;
+    off_t pos;
     size_t remain;
     ssize_t ret;
 
-    off = lseek(fd, pblk * PBLK_SIZE, SEEK_SET);
-    if (off == (off_t)-1) {
+    pos = lseek(fd, pblk * PBLK_SIZE, SEEK_SET);
+    if (pos == (off_t)-1) {
         error("Failed to seek\n");
     }
 
@@ -27,10 +27,10 @@ pblk_write(int fd, size_t pblk, size_t count, const u8* data)
 
 int
 cbd_format(const char* dev,
-           uint64_t poff, uint64_t psize,
-           uint64_t lsize, uint16_t lshift)
+           uint64_t psize, uint16_t lshift, uint64_t lsize)
 {
     int devfd;
+    uint32_t lblk_size;
     struct cbd_header header;
     uint8_t pblkbuf[PBLK_SIZE];
     uint64_t pblk;
@@ -42,23 +42,36 @@ cbd_format(const char* dev,
     }
 
     if (!psize) {
-        off_t len;
-        len = lseek(devfd, 0, SEEK_END);
-        if (len == (off_t)-1) {
+        off_t pos;
+        pos = lseek(devfd, 0, SEEK_END);
+        if (pos == (off_t)-1) {
             error("Cannot seek device\n");
         }
-        psize = len >> PBLK_SHIFT;
-    }
-    if (!lsize) {
-        lsize = psize * CBD_DEFAULT_COMPRESSION_FACTOR;
+        psize = pos / PBLK_SIZE * PBLK_SIZE;
     }
     if (!lshift) {
         lshift = CBD_DEFAULT_LOGICAL_BLOCK_SHIFT;
     }
+    lblk_size = 1 << (lshift + PBLK_SHIFT);
+    if (!lsize) {
+        /* XXX: Why is the cast needed here? */
+        lsize = (uint64_t)(psize * CBD_DEFAULT_COMPRESSION_FACTOR) / lblk_size * lblk_size;
+    }
+
+    if (psize % PBLK_SIZE) {
+        error("Physical size %lu is not a multiple of %u bytes\n", (ulong)psize, (uint)PBLK_SIZE);
+    }
+    if (lshift < LBLK_SHIFT_MIN || lshift > LBLK_SHIFT_MAX) {
+        error("Logical shift %hu is not in [%u,%u]\n", (ushort)lshift, (uint)LBLK_SHIFT_MIN, (uint)LBLK_SHIFT_MAX);
+    }
+    if (lsize % (1 << (lshift + PBLK_SHIFT))) {
+        error("Logical size %lu is not a multiple of %u bytes\n", (ulong)psize, (uint)lblk_size);
+    }
 
     printf("%s: paramaters...\n", __func__);
-    printf("  poff=%lu psize=%lu\n", (unsigned long)poff, (unsigned long)psize);
-    printf("  lsize=%lu lshift=%hu\n", (unsigned long)lsize, (unsigned short)lshift);
+    printf("  psize=%lu\n", (unsigned long)psize);
+    printf("  lshift=%hu\n", (unsigned short)lshift);
+    printf("  lsize=%lu\n", (unsigned long)lsize);
     memset(&header, 0, sizeof(header));
     memcpy(header.magic, CBD_MAGIC, sizeof(header.magic));
     header.version_major = CBD_VERSION_MAJOR;
@@ -66,12 +79,12 @@ cbd_format(const char* dev,
     header.params.algorithm = CBD_ALG_LZ4;
     header.params.compression = 1;
     header.params.lblk_shift = lshift;
-    header.params.nr_pblk = psize;
+    header.params.nr_pblk = psize / PBLK_SIZE;
     /* XXX: Initial estimate */
-    header.params.lblk_per_zone = zone_data_len(&header.params) * (lsize >> lshift) / psize;
+    header.params.lblk_per_zone = zone_data_len(&header.params) * (lsize / lblk_size) / (psize / PBLK_SIZE);
     printf("  initial estimate for lblk_per_zone: %lu\n", (unsigned long)header.params.lblk_per_zone);
-    header.params.nr_zones = (psize - CBD_HEADER_BLOCKS) / zone_len(&header.params);
-    header.params.lblk_per_zone = DIV_ROUND_UP((lsize >> lshift), header.params.nr_zones);
+    header.params.nr_zones = ((psize >> PBLK_SHIFT) - CBD_HEADER_BLOCKS) / zone_len(&header.params);
+    header.params.lblk_per_zone = DIV_ROUND_UP(lsize / lblk_size, header.params.nr_zones);
     printf("%s: parameters...\n", __func__);
     printf("  lblk_shift=%hu\n", (unsigned short)header.params.lblk_shift);
     printf("  nr_pblk=%lu\n", (unsigned long)header.params.nr_pblk);
@@ -81,7 +94,7 @@ cbd_format(const char* dev,
     memset(pblkbuf, 0, sizeof(pblkbuf));
     cbd_header_put(pblkbuf, &header);
 
-    pblk = poff;
+    pblk = 0;
     pblk_write(devfd, pblk, 1, pblkbuf);
     pblk += CBD_HEADER_BLOCKS;
 
diff --git a/libcbd/open.c b/libcbd/open.c
index aebd20b..9ea7ac5 100644
--- a/libcbd/open.c
+++ b/libcbd/open.c
@@ -10,6 +10,7 @@ device_logical_size(const char* dev)
     int fd;
     uint8_t pblkbuf[PBLK_SIZE];
     struct cbd_header header;
+    uint64_t lblk_size;
 
     fd = open(dev, O_RDONLY);
     if (fd < 0) {
@@ -18,18 +19,23 @@ device_logical_size(const char* dev)
     if (read(fd, pblkbuf, sizeof(pblkbuf)) != sizeof(pblkbuf)) {
         error("Cannot read device\n");
     }
-    cbd_header_get(pblkbuf, &header);
     close(fd);
+    cbd_header_get(pblkbuf, &header);
+    if (memcmp(header.magic, CBD_MAGIC, sizeof(header.magic)) != 0) {
+        error("Bad magic\n");
+    }
 
-    return (header.params.lblk_per_zone << header.params.lblk_shift) * header.params.nr_zones;
+    lblk_size = header.params.lblk_per_zone * header.params.nr_zones;
+
+    return (lblk_size << (header.params.lblk_shift + PBLK_SHIFT));
 }
 
 int
 cbd_open(const char* dev,
-         uint64_t loff, uint64_t lsize,
          const char* name)
 {
     int ret;
+    uint64_t lsize;
     struct stat st;
     struct dm_task* dmt;
     uint32_t cookie = 0;
@@ -41,10 +47,7 @@ cbd_open(const char* dev,
     if (!S_ISBLK(st.st_mode)) {
         error("Not a block device\n");
     }
-
-    if (!lsize) {
-        lsize = device_logical_size(dev);
-    }
+    lsize = device_logical_size(dev);
 
     dmt = dm_task_create(DM_DEVICE_CREATE);
     if (!dmt) {
@@ -54,12 +57,11 @@ cbd_open(const char* dev,
     if (ret == 0) {
         error("dm_task_set_name failed\n");
     }
-    printf("%s: start_sector=%lu num_sectors=%lu\n", __func__,
-           (unsigned long)(loff * PBLK_PER_SECTOR),
-           (unsigned long)(lsize * PBLK_PER_SECTOR));
+    printf("%s: start_sector=0 num_sectors=%lu\n", __func__,
+           (unsigned long)(lsize / SECTOR_SIZE));
     ret = dm_task_add_target(dmt,
-                             loff * PBLK_PER_SECTOR,
-                             lsize * PBLK_PER_SECTOR,
+                             0,
+                             lsize / SECTOR_SIZE,
                              "compress",
                              dev);
     if (ret == 0) {
diff --git a/libcbd/resize.c b/libcbd/resize.c
index 9d4bc95..0bc9586 100644
--- a/libcbd/resize.c
+++ b/libcbd/resize.c
@@ -4,7 +4,7 @@
 
 int
 cbd_resize(const char* dev,
-           uint64_t poff, uint64_t psize)
+           uint64_t lsize)
 {
     error("Not implemented\n");