diff --git a/README b/README index ab79a42..4f6d649 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ This is a device mapper block compression driver. Note: - Sectors are always 512 bytes (kernel constant). - - Physical blocks are variable 512b .. 4kb. + - Physical blocks are always 4kb. - Logical blocks are variable 4kb .. 4mb. - All integers are little endian. @@ -17,11 +17,9 @@ Block device layout: - u8 compression hi nybble: algorithm (1=lz4, 2=zlib, ...) [1] lo nybble: level (1..9) [1] - - u8 pblk_shift (0..3) [3 = 4kb] - u8 lblk_shift (1..10) [4 = 64kb (*)] - u8 lba_elem_pblk_bytes (2, 4, 6) - - u8 pbat_shift [0] - - u8 pad + - u8[3] pad - u32 nr_zones - u32 lblk_per_zone - byte[40] reserved @@ -33,9 +31,8 @@ Block device layout: - byte[384] reserved - pblk[] zone ... vector of zone -(*) The maximum lblk_shift may be (and usually is) less than 10 because - lblk_alloc size must be <= pblk size. When pblk_shift=1 (1024) and - lblk_alloc_16_32, the maximum lblk_shift is 8 (256kb). +(*) The maximum lblk_shift may be less than 10 because lblk_alloc size + must be <= pblk size. Device size limits: - Min: header plus one zone (header, pbat, lbat, data) @@ -43,19 +40,19 @@ Device size limits: - Max: 2^48 pblk = 1eb There are six different lblk_alloc sizes: - Struct name Size lblk_size device_pblk_size - =========== ==== ========= ================ - lblk_alloc_16_16 2+2*8 <= 64kb <= 64k - lblk_alloc_16_32 2+4*8 <= 64kb <= 4g - lblk_alloc_16_48 2+6*8 <= 64kb <= 256t - lblk_alloc_32_16 4+2*8 > 64kb <= 64k - lblk_alloc_32_32 4+4*8 > 64kb <= 4g - lblk_alloc_32_48 4+6*8 > 64kb <= 256t + Struct name Size lblk_shift lblk_size device pblks + =========== ===== ========== ========= ============ + lblk_alloc_16_16 2+2*n 1..10 <= 64kb <= 64k + lblk_alloc_16_32 2+4*n 1..9 <= 64kb <= 4g + lblk_alloc_16_48 2+6*n 1..9 <= 64kb <= 256t + lblk_alloc_32_16 4+2*n 1..10 > 64kb <= 64k + lblk_alloc_32_32 4+4*n 1..9 > 64kb <= 4g + lblk_alloc_32_48 4+6*n 1..9 > 64kb <= 256t Zone layout: - - byte[pblk_size*pbat_len] Physical block allocation table (pbat) - - lblk_alloc_x_y[] Logical block allocation table (lbat) - Note: padded to pblk size - - data[] Data - One pblk per bit in pbat + - byte[pblk_size] Physical block allocation table (pbat) + - lblk_alloc_x_y[] Logical block allocation table (lbat) + Note: padded to pblk size + - data[] Data + One pblk per bit in pbat diff --git a/cbd/cbd.c b/cbd/cbd.c index 1a3987e..3e75790 100644 --- a/cbd/cbd.c +++ b/cbd/cbd.c @@ -93,21 +93,20 @@ parse_boolean_arg(const char* arg, uint64_t* val) struct profile { const char* name; - uint pblksize; uint lblksize; enum cbd_alg alg; uint level; }; static struct profile profiles[] = { - { "performance", 1*1024, 4*1024, CBD_ALG_LZ4, 1 }, - { "mixed", 4*1024, 64*1024, CBD_ALG_LZ4, 3 }, - { "read-mostly", 4*1024, 64*1024, CBD_ALG_ZLIB, 6 }, - { "archive", 4*1024, 256*1024, CBD_ALG_ZLIB, 9 }, + { "performance", 4*1024, CBD_ALG_LZ4, 1 }, + { "mixed", 64*1024, CBD_ALG_LZ4, 3 }, + { "read-mostly", 64*1024, CBD_ALG_ZLIB, 6 }, + { "archive", 256*1024, CBD_ALG_ZLIB, 9 }, }; static bool parse_profile(const char* name, - uint* pblksize, uint* lblksize, + uint* lblksize, enum cbd_alg* alg, uint* level) { uint n; @@ -115,7 +114,6 @@ parse_profile(const char* name, for (n = 0; n < ARRAY_SIZE(profiles); ++n) { struct profile* profile = &profiles[n]; if (!strcmp(profile->name, name)) { - *pblksize = profile->pblksize; *lblksize = profile->lblksize; *alg = profile->alg; *level = profile->level; @@ -152,12 +150,10 @@ usage(void) "\n"); fprintf(stderr, "Commands:\n" " format [opts] Create (format) a compressed device\n" - " -P --pbat-size Physical block allocation table size [1]\n" " -S --pysical-size Physical size [device size]\n" " -Z --compress-level Compression level [1]\n" " -c --compress-factor Compression factor [2.0]\n" " -l --logical-blksize Logical block size\n" - " -p --physical-blksize Physical block size\n" " -s --size Logical size\n" " -z --compress-alg Compression algorithm [lz4]\n" " --detect-zeros Detect and free zero blocks at runtime\n" @@ -167,10 +163,10 @@ usage(void) " -c and -s are different ways of specifying the compressed device size.\n" " Only one may be used, not both.\n" " Profiles:\n" - " performance: 1k pblk, 4k lblk, lz4 level 1\n" - " mixed: 4k pblk, 64k lblk, lz4 level 3\n" - " read-mostly: 4k pblk, 64k lblk, zlib level 6\n" - " archive: 4k pblk, 256k lblk, zlib level 9\n" + " performance: 4k lblk, lz4 level 1\n" + " mixed: 64k lblk, lz4 level 3\n" + " read-mostly: 64k lblk, zlib level 6\n" + " archive: 256k lblk, zlib level 9\n" "\n" " open [opts] Open an existing compressed device\n" " -c --cache-pages Set cache pages\n" @@ -202,14 +198,12 @@ usage(void) static int do_format(int argc, char** argv) { - static const char short_opts[] = "P:S:Z:c:l:p:s:z:"; + static const char short_opts[] = "S:Z:c:l:s:z:"; static const struct option long_opts[] = { - { "pbat-size", required_argument, NULL, 'P' }, { "physical-size", required_argument, NULL, 'S' }, { "compress-level", required_argument, NULL, 'Z' }, { "compress-factor", required_argument, NULL, 'c' }, { "logical-blksize", required_argument, NULL, 'l' }, - { "physical-blksize", required_argument, NULL, 'p' }, { "size", required_argument, NULL, 's' }, { "compress-alg", required_argument, NULL, 'z' }, { "detect-zeros", optional_argument, NULL, 0x1 }, @@ -221,31 +215,18 @@ do_format(int argc, char** argv) uint64_t optval; uint64_t psize = 0; uint64_t lsize = 0; - uint pblksize = PAGE_SIZE; uint lblksize = 16 * PAGE_SIZE; - uint pbatsize = 1; uint16_t flags = 0; enum cbd_alg alg = CBD_ALG_LZ4; uint level = 1; bool full_init = false; - uint8_t pshift; uint8_t lshift; - uint8_t pbatshift; const char* dev; while ((opt = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) { switch (opt) { - case 'P': - if (!parse_numeric_arg(optarg, &optval)) { - error("Failed to parse \"%s\"\n", optarg); - } - if (optval < 1) { - error("Size \"%s\" is not a valid pbat len\n", optarg); - } - pbatsize = optval; - break; case 'S': if (!parse_numeric_arg(optarg, &optval)) { error("Failed to parse \"%s\"\n", optarg); @@ -273,15 +254,6 @@ do_format(int argc, char** argv) } lblksize = optval; break; - case 'p': - if (!parse_numeric_arg(optarg, &optval)) { - error("Failed to parse \"%s\"\n", optarg); - } - if (optval & (optval - 1)) { - error("Size \"%s\" is not a valid block size\n", optarg); - } - pblksize = optval; - break; case 's': if (!parse_numeric_arg(optarg, &optval)) { error("Failed to parse \"%s\"\n", optarg); @@ -312,7 +284,7 @@ do_format(int argc, char** argv) } break; case 0x2: - if (!parse_profile(optarg, &pblksize, &lblksize, &alg, &level)) { + if (!parse_profile(optarg, &lblksize, &alg, &level)) { error("Invalid profile \"%s\"\n", optarg); } break; @@ -323,25 +295,17 @@ do_format(int argc, char** argv) usage(); } } - pshift = get_shift(pblksize, SECTOR_SIZE); - if (pshift < PBLK_SHIFT_MIN || pshift > PBLK_SHIFT_MAX) { - error("Invalid physical block size %u\n", pblksize); - } - lshift = get_shift(lblksize, pblksize); + lshift = get_shift(lblksize, PBLK_SIZE); if (lshift < LBLK_SHIFT_MIN || lshift > LBLK_SHIFT_MAX) { error("Invalid logical block size %u\n", lblksize); } - pbatshift = get_shift(pbatsize, 1); - if (pbatshift < PBAT_SHIFT_MIN || pbatshift > PBAT_SHIFT_MAX) { - error("Invalid pbat len %u\n", pbatsize); - } if (argc - optind != 1) { usage(); } dev = argv[optind++]; cbd_format(dev, flags, alg, level, - pshift, lshift, pbatshift, psize, lsize, + lshift, psize, lsize, full_init); return 0; diff --git a/dm-compress/compress.c b/dm-compress/compress.c index 52b1812..d98b9ee 100644 --- a/dm-compress/compress.c +++ b/dm-compress/compress.c @@ -71,15 +71,15 @@ blkdev_pages(struct block_device* bdev) } static inline u64 -blkdev_pblks(struct block_device* bdev, struct cbd_params* params) +blkdev_pblks(struct block_device* bdev) { - return i_size_read(bdev->bd_inode) >> (SECTOR_SHIFT + params->pblk_shift); + return i_size_read(bdev->bd_inode) >> PBLK_SHIFT; } static inline u64 -target_pblks(struct dm_target* ti, struct cbd_params* params) +target_pblks(struct dm_target* ti) { - return ti->len >> params->pblk_shift; + return ti->len >> PBLK_SHIFT; } static inline u64 @@ -107,7 +107,7 @@ compress_read_header(struct compress* c, char** errorp) } buf = page_address(page); - ret = pblk_read_wait(&c->kparams, 0, 1, page); + ret = pblk_read_wait(&c->kparams, 0, page); if (ret) { *errorp = "Header: failed to read"; goto out; @@ -156,12 +156,6 @@ compress_read_header(struct compress* c, char** errorp) ret = -EINVAL; goto out; } - if (header.params.pblk_shift < PBLK_SHIFT_MIN || - header.params.pblk_shift > PBLK_SHIFT_MAX) { - *errorp = "Header: pblk_shift out of bounds"; - ret = -EINVAL; - goto out; - } if (header.params.lblk_shift < LBLK_SHIFT_MIN || header.params.lblk_shift > LBLK_SHIFT_MAX) { *errorp = "Header: lblk_shift out of bounds"; @@ -175,18 +169,7 @@ compress_read_header(struct compress* c, char** errorp) ret = -EINVAL; goto out; } - if (header.params.pbat_shift < PBAT_SHIFT_MIN || - header.params.pbat_shift > PBAT_SHIFT_MAX) { - *errorp = "Header: pbat_shift out of bounds"; - ret = -EINVAL; - goto out; - } - if (pbat_len(&header.params) * pblk_size(&header.params) > PAGE_SIZE) { - *errorp = "Header: pbat size too large"; - ret = -EINVAL; - goto out; - } - if (lba_len(&header.params) > pblk_size(&header.params)) { + if (lba_len(&header.params) > PBLK_SIZE) { *errorp = "Header: lba elem size too large"; ret = -EINVAL; goto out; @@ -199,10 +182,8 @@ compress_read_header(struct compress* c, char** errorp) printk(KERN_INFO "%s: parameters...\n", __func__); printk(KERN_INFO " compression=0x%02x\n", (unsigned int)header.params.compression); - printk(KERN_INFO " pblk_shift=%hu\n", (unsigned short)header.params.pblk_shift); printk(KERN_INFO " lblk_shift=%hu\n", (unsigned short)header.params.lblk_shift); printk(KERN_INFO " lba_elem_pblk_bytes=%hu\n", (unsigned short)header.params.lba_elem_pblk_bytes); - printk(KERN_INFO " pbat_shift=%hu\n", (unsigned short)header.params.pbat_shift); printk(KERN_INFO " nr_zones=%u\n", (unsigned int)header.params.nr_zones); printk(KERN_INFO " lblk_per_zone=%u\n", (unsigned int)header.params.lblk_per_zone); printk(KERN_INFO "%s: stats...\n", __func__); @@ -237,7 +218,7 @@ compress_write_header(struct compress* c) memcpy(&header.params, &c->kparams.params, sizeof(header.params)); memcpy(&header.stats, &c->kstats.stats, sizeof(header.stats)); cbd_header_put(buf, &header); - ret = pblk_write_wait(&c->kparams, 0, 1, page); + ret = pblk_write_wait(&c->kparams, 0, page); if (ret) { printk(KERN_ERR "%s: failed to write header\n", __func__); } @@ -263,21 +244,12 @@ compress_write_header_dirty(struct compress* c) static void init_zone(struct compress* c, u32 zone, struct page* page) { - u32 pblk_per_page = PAGE_SIZE / pblk_size(&c->kparams.params); u64 zone_pblk = zone_off(&c->kparams.params, zone); u32 nr_pblk = zone_metadata_len(&c->kparams.params); u32 pblk_idx; - u64 pblkv[PBLK_IOV_MAX]; - u32 iov_len; - u32 n; - pblk_idx = 0; - while (pblk_idx < nr_pblk) { - iov_len = min(nr_pblk - pblk_idx, pblk_per_page); - for (n = 0; n < iov_len; ++n) { - pblkv[n] = zone_pblk + pblk_idx++; - } - pblk_writev(&c->kparams, pblkv, iov_len, page); + for (pblk_idx = 0; pblk_idx < nr_pblk; ++pblk_idx) { + pblk_write(&c->kparams, zone_pblk + pblk_idx, page); lock_page(page); } } @@ -489,8 +461,7 @@ compress_attr_show(struct kobject* kobj, struct attribute* attr, val = c->kstats.stats.pblk_used; break; case attr_pblk_total: - val = pbat_len(&c->kparams.params) * - pblk_size_bits(&c->kparams.params) * + val = pblk_size_bits(&c->kparams.params) * c->kparams.params.nr_zones; break; case attr_lblk_used: @@ -711,33 +682,33 @@ compress_ctr(struct dm_target *ti, unsigned int argc, char **argv) /* ti->error already set */ goto err; } - if (blkdev_pblks(c->dev->bdev, &c->kparams.params) < + if (blkdev_pblks(c->dev->bdev) < zone_off(&c->kparams.params, c->kparams.params.nr_zones)) { printk(KERN_ERR "%s: physical device too small: " "actual=%lu, needed=%lu\n", __func__, - (unsigned long)blkdev_pblks(c->dev->bdev, &c->kparams.params), + (unsigned long)blkdev_pblks(c->dev->bdev), (unsigned long)zone_off(&c->kparams.params, c->kparams.params.nr_zones)); ti->error = "Physical device too small"; ret = -EINVAL; goto err; } - if (target_pblks(ti, &c->kparams.params) != + if (target_pblks(ti) != logical_pblks(&c->kparams.params)) { printk(KERN_WARNING "%s: incorrect target device size: " "expected pblks=%lu, actual pblks=%lu\n", __func__, (unsigned long)logical_pblks(&c->kparams.params), - (unsigned long)target_pblks(ti, &c->kparams.params)); + (unsigned long)target_pblks(ti)); } if (!cache_pages) { /* Minimum of 1/1k RAM and 1/64k device size */ - cache_pages = min((unsigned int)(totalram_pages >> 10), + cache_pages = min((unsigned int)(totalram_pages() >> 10), (unsigned int)(blkdev_pages(c->dev->bdev) >> 16)); if (cache_pages < 32 * 2 * num_online_cpus()) { cache_pages = 32 * 2 * num_online_cpus(); } } printk(KERN_INFO "%s: totalram_pages=%lu blkdev_pages=%lu cache_pages=%u\n", - __func__, totalram_pages, (unsigned long)blkdev_pages(c->dev->bdev), cache_pages); + __func__, totalram_pages(), (unsigned long)blkdev_pages(c->dev->bdev), cache_pages); if (c->kparams.params.flags & CBD_FLAG_DIRTY) { printk(KERN_INFO "Warning: device was not properly closed\n"); diff --git a/dm-compress/lbatpblk.c b/dm-compress/lbatpblk.c index 0122212..620060a 100644 --- a/dm-compress/lbatpblk.c +++ b/dm-compress/lbatpblk.c @@ -96,7 +96,7 @@ lbatpblk_flush(struct lbatpblk* lp) ret = -EIO; goto unlock; } - pblk_write(lp->kparams, lp->pblk, 1, lp->page); + pblk_write(lp->kparams, lp->pblk, lp->page); mutex_unlock(&lp->lock); mutex_lock(&lp->kstats->lock); ++lp->kstats->lbatpblk_w; @@ -117,7 +117,7 @@ lbatpblk_read(struct lbatpblk* lp) int ret = 0; BUG_ON(lbatpblk_error(lp)); - ret = pblk_read_wait(lp->kparams, lp->pblk, 1, lp->page); + ret = pblk_read_wait(lp->kparams, lp->pblk, lp->page); mutex_lock(&lp->kstats->lock); ++lp->kstats->lbatpblk_r; mutex_unlock(&lp->kstats->lock); diff --git a/dm-compress/lbatview.c b/dm-compress/lbatview.c index 23c618c..0ff2b1a 100644 --- a/dm-compress/lbatview.c +++ b/dm-compress/lbatview.c @@ -263,7 +263,7 @@ lbatview_elem_off(struct lbatview* lv, u64 lblk) /* The offset of the element in the (full) lbat. */ u32 lbat_elem_off = zone_rel_lblk * lba_len(&lv->kparams->params); /* The offset of the first view pblk. */ - u32 lbatview_off = pblk_size(&lv->kparams->params) * + u32 lbatview_off = PBLK_SIZE * (lv->pblk - lbat_off(&lv->kparams->params, lv_zone)); return lbat_elem_off - lbatview_off; @@ -272,7 +272,7 @@ lbatview_elem_off(struct lbatview* lv, u64 lblk) static void lbatview_rmem(struct lbatview* lv, u32 off, u32 len, void* buf) { - u32 pblk_len = pblk_size(&lv->kparams->params); + u32 pblk_len = PBLK_SIZE; BUG_ON(off + len > 2 * pblk_len); if (off < pblk_len && off + len > pblk_len) { @@ -296,7 +296,7 @@ lbatview_rmem(struct lbatview* lv, u32 off, u32 len, void* buf) static void lbatview_wmem(struct lbatview* lv, u32 off, u32 len, void* buf) { - u32 pblk_len = pblk_size(&lv->kparams->params); + u32 pblk_len = PBLK_SIZE; BUG_ON(off + len > 2 * pblk_len); if (off < pblk_len && off + len > pblk_len) { @@ -336,13 +336,13 @@ lbatview_elem_realloc(struct lbatview* lv, u64 lblk, u32 len) elem_off = lbatview_elem_off(lv, lblk); req_nalloc = (len == CBD_UNCOMPRESSED) ? lblk_per_pblk(&lv->kparams->params) : - DIV_ROUND_UP(len, pblk_size(&lv->kparams->params)); + DIV_ROUND_UP(len, PBLK_SIZE); elem_lelen = 0; lbatview_rmem(lv, elem_off, lba_elem_len_bytes(&lv->kparams->params), &elem_lelen); elem_len = __le32_to_cpu(elem_lelen); cur_nalloc = (elem_len == CBD_UNCOMPRESSED) ? lblk_per_pblk(&lv->kparams->params) : - DIV_ROUND_UP(elem_len, pblk_size(&lv->kparams->params)); + DIV_ROUND_UP(elem_len, PBLK_SIZE); old_nalloc = cur_nalloc; while (cur_nalloc < req_nalloc) { @@ -557,7 +557,7 @@ lbatviewcache_get(struct lbatviewcache* lvc, u64 lblk) zone_lbat_pblk = lbat_off(lvc->params, zone); rel_lblk = lblk - lvc->params->lblk_per_zone * zone; lbat_offset = rel_lblk * lba_len(lvc->params); - rel_pblk = lbat_offset / pblk_size(lvc->params); + rel_pblk = lbat_offset / PBLK_SIZE; pblk = zone_lbat_pblk + rel_pblk; count = (rel_pblk == lbat_len(lvc->params) - 1) ? 1 : 2; diff --git a/dm-compress/lbd.c b/dm-compress/lbd.c index 333a250..de1a4d2 100644 --- a/dm-compress/lbd.c +++ b/dm-compress/lbd.c @@ -53,7 +53,7 @@ static inline bool lblk_is_zeros(struct cbd_params* params, struct lbd* lbd) { u32 off; - u32 len = lblk_per_pblk(params) * pblk_size(params); + u32 len = lblk_per_pblk(params) * PBLK_SIZE; if (!(params->flags & CBD_FLAG_DETECT_ZEROS)) { return false; @@ -101,7 +101,7 @@ lblk_compress_lz4(struct lbd* lbd) clen = LZ4_compress_fast(lbd->buf, state->buf, lblk_size(&lbd->kparams->params), lblk_size(&lbd->kparams->params) - - pblk_size(&lbd->kparams->params), + PBLK_SIZE, cbd_compression_level_get(&lbd->kparams->params), state->lz4_workmem); if (clen <= 0) { @@ -159,8 +159,7 @@ lblk_compress_zlib(struct lbd* lbd) stream->next_in = lbd->buf; stream->avail_in = lblk_size(&lbd->kparams->params); stream->next_out = state->buf; - stream->avail_out = lblk_size(&lbd->kparams->params) - - pblk_size(&lbd->kparams->params); + stream->avail_out = lblk_size(&lbd->kparams->params) - PBLK_SIZE; ret = zlib_deflate(stream, Z_FINISH); if (ret != Z_STREAM_END) { put_cpu(); @@ -337,13 +336,10 @@ lbd_flush(struct lbd* lbd) { int ret = 0; u32 nr_pages = DIV_ROUND_UP(lblk_size(&lbd->kparams->params), PAGE_SIZE); - u32 pblk_per_page = PAGE_SIZE / pblk_size(&lbd->kparams->params); int err; u32 nr_pblk; u32 pblk_idx; - u32 pg_idx; - u64 pblkv[PBLK_IOV_MAX]; - u32 iov_len; + u64* pblkv; u32 n; mutex_lock(&lbd->lock); @@ -362,11 +358,11 @@ lbd_flush(struct lbd* lbd) } lbd->c_len = lblk_compress(lbd); if (lbd->c_len > 0) { - u32 c_blkrem = lbd->c_len % pblk_size(&lbd->kparams->params); + u32 c_blkrem = lbd->c_len % PBLK_SIZE; if (c_blkrem) { memset(lbd->buf + lbd->c_len, 0, c_blkrem); } - nr_pblk = DIV_ROUND_UP(lbd->c_len, pblk_size(&lbd->kparams->params)); + nr_pblk = DIV_ROUND_UP(lbd->c_len, PBLK_SIZE); } else { lbd->c_len = CBD_UNCOMPRESSED; @@ -377,17 +373,16 @@ lbd_flush(struct lbd* lbd) lbd->kparams->params.flags |= CBD_FLAG_ERROR; goto unlock; } - for (pblk_idx = 0, pg_idx = 0; pblk_idx < nr_pblk; ++pg_idx) { - iov_len = min(nr_pblk - pblk_idx, pblk_per_page); - for (n = 0; n < iov_len; ++n) { - pblkv[n] = lbatview_elem_pblk(lbd->lv, lbd->lblk, pblk_idx++); - BUG_ON(pblkv[n] == PBLK_NONE); - } - pblk_writev(lbd->kparams, pblkv, iov_len, lbd->pagev[pg_idx]); + pblkv = kmalloc(nr_pblk * sizeof(u64), GFP_KERNEL); + for (pblk_idx = 0; pblk_idx < nr_pblk; ++pblk_idx) { + pblkv[pblk_idx] = lbatview_elem_pblk(lbd->lv, lbd->lblk, pblk_idx); + BUG_ON(pblkv[pblk_idx] == PBLK_NONE); } - while (pg_idx < nr_pages) { - unlock_page(lbd->pagev[pg_idx++]); + pblk_writev(lbd->kparams, pblkv, lbd->pagev, nr_pblk); + while (pblk_idx < nr_pages) { + unlock_page(lbd->pagev[pblk_idx++]); } + kfree(pblkv); mutex_lock(&lbd->kstats->lock); ++lbd->kstats->lbd_w; mutex_unlock(&lbd->kstats->lock); @@ -413,13 +408,9 @@ static int lbd_read(struct lbd* lbd) { int ret = 0; - u32 pblk_per_page = PAGE_SIZE / pblk_size(&lbd->kparams->params); u32 nr_pblk; u32 pblk_idx; - u32 pg_idx; - u64 pblkv[PBLK_IOV_MAX]; - u32 iov_len; - u32 n; + u64* pblkv = NULL; BUG_ON(lbd_error(lbd)); lbd->c_len = lbatview_elem_len(lbd->lv, lbd->lblk); @@ -429,28 +420,31 @@ lbd_read(struct lbd* lbd) else { nr_pblk = (lbd->c_len == CBD_UNCOMPRESSED) ? lblk_per_pblk(&lbd->kparams->params) : - DIV_ROUND_UP(lbd->c_len, pblk_size(&lbd->kparams->params)); + DIV_ROUND_UP(lbd->c_len, PBLK_SIZE); if (nr_pblk > lblk_per_pblk(&lbd->kparams->params)) { printk(KERN_ERR "%s: elem len %u out of range at lblk=%lu\n", __func__, lbd->c_len, (unsigned long)lbd->lblk); ret = -EIO; goto out; } - for (pblk_idx = 0, pg_idx = 0; pblk_idx < nr_pblk; ++pg_idx) { - iov_len = min(nr_pblk - pblk_idx, pblk_per_page); - for (n = 0; n < iov_len; ++n) { - pblkv[n] = lbatview_elem_pblk(lbd->lv, lbd->lblk, pblk_idx++); - if (pblkv[n] == PBLK_NONE) { - printk(KERN_ERR "%s: bad pblk\n", __func__); - ret = -EIO; - goto out; - } - } - ret = pblk_readv_wait(lbd->kparams, pblkv, iov_len, lbd->pagev[pg_idx]); - if (ret) { + pblkv = kmalloc(nr_pblk * sizeof(u64), GFP_KERNEL); + if (!pblkv) { + printk(KERN_ERR "%s: out of memory\n", __func__); + ret = -EIO; + goto out; + } + for (pblk_idx = 0; pblk_idx < nr_pblk; ++pblk_idx) { + pblkv[pblk_idx] = lbatview_elem_pblk(lbd->lv, lbd->lblk, pblk_idx); + if (pblkv[pblk_idx] == PBLK_NONE) { + printk(KERN_ERR "%s: bad pblk\n", __func__); + ret = -EIO; goto out; } } + ret = pblk_readv_wait(lbd->kparams, pblkv, lbd->pagev, nr_pblk); + if (ret) { + goto out; + } if (lbd->c_len != CBD_UNCOMPRESSED) { if (!lblk_decompress(lbd)) { printk(KERN_ERR "%s: decompress failed\n", __func__); @@ -465,6 +459,7 @@ lbd_read(struct lbd* lbd) mutex_unlock(&lbd->kstats->lock); out: + kfree(pblkv); return ret; } diff --git a/dm-compress/pbat.c b/dm-compress/pbat.c index 2374597..7d9988d 100644 --- a/dm-compress/pbat.c +++ b/dm-compress/pbat.c @@ -100,7 +100,7 @@ pbat_flush(struct pbat* pbat) goto unlock; } pblk = pbat_off(&pbat->kparams->params, pbat->zone); - pblk_write(pbat->kparams, pblk, pbat_len(&pbat->kparams->params), pbat->page); + pblk_write(pbat->kparams, pblk, pbat->page); mutex_unlock(&pbat->lock); mutex_lock(&pbat->kstats->lock); ++pbat->kstats->pbat_w; @@ -123,7 +123,7 @@ pbat_read(struct pbat* pbat) BUG_ON(pbat_error(pbat)); pblk = pbat_off(&pbat->kparams->params, pbat->zone); - ret = pblk_read_wait(pbat->kparams, pblk, pbat_len(&pbat->kparams->params), pbat->page); + ret = pblk_read_wait(pbat->kparams, pblk, pbat->page); mutex_lock(&pbat->kstats->lock); ++pbat->kstats->pbat_r; mutex_unlock(&pbat->kstats->lock); @@ -161,8 +161,7 @@ pbat_zone(struct pbat* pbat) u64 pbat_alloc(struct pbat* pbat) { - u32 bitsize = pblk_size_bits(&pbat->kparams->params) * - pbat_len(&pbat->kparams->params); + u32 bitsize = pblk_size_bits(&pbat->kparams->params); u32 idx; u64 pblk; @@ -192,8 +191,7 @@ out: int pbat_free(struct pbat* pbat, u64 pblk) { - u32 bitsize = pblk_size_bits(&pbat->kparams->params) * - pbat_len(&pbat->kparams->params); + u32 bitsize = pblk_size_bits(&pbat->kparams->params); u32 zone; u32 idx; diff --git a/dm-compress/util.c b/dm-compress/util.c index fc86548..402d887 100644 --- a/dm-compress/util.c +++ b/dm-compress/util.c @@ -99,11 +99,10 @@ cbd_free_pagev(struct page** pagev, size_t len) static struct bio* pblk_io_prepare(struct block_device* bdev, unsigned int op, - u32 pblk_len, u64 pblk, u32 count, struct page* page, u32 page_off) + u64 pblk, struct page* page) { struct bio* bio; - BUG_ON(page_off + pblk_len * count > PAGE_SIZE); bio = bio_alloc(GFP_KERNEL, 1); if (!bio) { printk(KERN_ERR "%s: out of memory\n", __func__); @@ -112,23 +111,38 @@ pblk_io_prepare(struct block_device* bdev, unsigned int op, bio_set_dev(bio, bdev); bio->bi_opf = op; - bio->bi_iter.bi_sector = pblk * (pblk_len / SECTOR_SIZE); - if (bio_add_page(bio, page, pblk_len * count, page_off) == 0) { + bio->bi_iter.bi_sector = pblk * (PBLK_SIZE / SECTOR_SIZE); + if (bio_add_page(bio, page, PBLK_SIZE, 0) == 0) { BUG(); } return bio; } +void +pblk_endio(struct bio* bio) +{ + struct compress_params* kparams = bio->bi_private; + struct page* page = bio->bi_io_vec[0].bv_page; + + if (bio->bi_status != BLK_STS_OK) { + printk(KERN_ERR "%s: I/O error\n", __func__); + kparams->params.flags |= CBD_FLAG_ERROR; + SetPageError(page); + } + ClearPageDirty(page); + unlock_page(page); + bio_put(bio); +} + int pblk_read_wait(struct compress_params* kparams, - u64 pblk, u32 count, struct page* page) + u64 pblk, struct page* page) { int ret; struct bio* bio; - bio = pblk_io_prepare(kparams->dev, REQ_OP_READ, - pblk_size(&kparams->params), pblk, count, page, 0); + bio = pblk_io_prepare(kparams->dev, REQ_OP_READ, pblk, page); if (!bio) { printk(KERN_ERR "%s: out of memory\n", __func__); return -ENOMEM; @@ -144,28 +158,31 @@ pblk_read_wait(struct compress_params* kparams, int pblk_readv_wait(struct compress_params* kparams, - u64* pblkv, u32 count, struct page* page) + u64* pblkv, struct page** pagev, u32 count) { int ret = 0; - u32 pblk_len = pblk_size(&kparams->params); - u32 n; - u32 page_off; + u32 idx; struct bio* bio; /* XXX: Issue no-blocking reads for parallelism? */ - for (n = 0, page_off = 0; n < count; ++n, page_off += pblk_len) { - bio = pblk_io_prepare(kparams->dev, REQ_OP_READ, - pblk_len, pblkv[n], 1, page, page_off); + for (idx = 0; idx < count; ++idx) { + bio = pblk_io_prepare(kparams->dev, REQ_OP_READ, pblkv[idx], pagev[idx]); if (!bio) { printk(KERN_ERR "%s: out of memory\n", __func__); - return -ENOMEM; + ret = -ENOMEM; + goto iowait; } - ret = submit_bio_wait(bio); - if (ret) { - printk(KERN_ERR "%s: submit_bio_wait failed: %d\n", __func__, ret); - return ret; + bio->bi_end_io = pblk_endio; + bio->bi_private = kparams; + submit_bio(bio); + } +iowait: + while (idx > 0) { + --idx; + lock_page(pagev[idx]); + if (PageError(pagev[idx])) { + ret = -EIO; } - bio_put(bio); } return ret; @@ -173,13 +190,12 @@ pblk_readv_wait(struct compress_params* kparams, int pblk_write_wait(struct compress_params* kparams, - u64 pblk, u32 count, struct page* page) + u64 pblk, struct page* page) { int ret; struct bio* bio; - bio = pblk_io_prepare(kparams->dev, REQ_OP_WRITE, - pblk_size(&kparams->params), pblk, count, page, 0); + bio = pblk_io_prepare(kparams->dev, REQ_OP_WRITE, pblk, page); if (!bio) { printk(KERN_ERR "%s: out of memory\n", __func__); return -ENOMEM; @@ -194,30 +210,13 @@ pblk_write_wait(struct compress_params* kparams, return ret; } -void -pblk_write_endio(struct bio* bio) -{ - struct compress_params* kparams = bio->bi_private; - struct page* page = bio->bi_io_vec[0].bv_page; - - if (bio->bi_status != BLK_STS_OK) { - printk(KERN_ERR "%s: I/O error\n", __func__); - kparams->params.flags |= CBD_FLAG_ERROR; - SetPageError(page); - } - ClearPageDirty(page); - unlock_page(page); - bio_put(bio); -} - void pblk_write(struct compress_params* kparams, - u64 pblk, u32 count, struct page* page) + u64 pblk, struct page* page) { struct bio* bio; - bio = pblk_io_prepare(kparams->dev, REQ_OP_WRITE, - pblk_size(&kparams->params), pblk, count, page, 0); + bio = pblk_io_prepare(kparams->dev, REQ_OP_WRITE, pblk, page); if (!bio) { printk(KERN_ERR "%s: out of memory\n", __func__); kparams->params.flags |= CBD_FLAG_ERROR; @@ -225,65 +224,18 @@ pblk_write(struct compress_params* kparams, unlock_page(page); return; } - bio->bi_end_io = pblk_write_endio; + bio->bi_end_io = pblk_endio; bio->bi_private = kparams; submit_bio(bio); } void pblk_writev(struct compress_params* kparams, - u64* pblkv, u32 count, struct page* page) + u64* pblkv, struct page** pagev, u32 count) { - u32 pblk_len = pblk_size(&kparams->params); u32 idx; - u32 page_off; - u32 nr_bio; - u64 pblk; - u32 iov_nr_pblk; - struct bio* parent_bio; - struct bio* bio; - BUG_ON(pblk_len * count > PAGE_SIZE); - parent_bio = NULL; - idx = 0; - page_off = 0; - nr_bio = 0; - while (idx < count) { - pblk = pblkv[idx]; - iov_nr_pblk = 1; - ++idx; - while (idx < count && pblkv[idx] == pblk + iov_nr_pblk) { - ++iov_nr_pblk; - ++idx; - } - bio = pblk_io_prepare(kparams->dev, REQ_OP_WRITE, - pblk_len, pblk, iov_nr_pblk, page, page_off); - if (!bio) { - printk(KERN_ERR "%s: out of memory\n", __func__); - goto err; - } - if (!parent_bio) { - bio->bi_end_io = pblk_write_endio; - bio->bi_private = kparams; - parent_bio = bio; - } - else { - bio_chain(bio, parent_bio); - parent_bio = bio; - } - page_off += pblk_len * iov_nr_pblk; - submit_bio(bio); + for (idx = 0; idx < count; ++idx) { + pblk_write(kparams, pblkv[idx], pagev[idx]); } - - return; - -err: - while (parent_bio) { - bio = parent_bio; - parent_bio = bio->bi_private; - bio_put(bio); - } - kparams->params.flags |= CBD_FLAG_ERROR; - SetPageError(page); - unlock_page(page); } diff --git a/include/cbdutil.h b/include/cbdutil.h index 97fab52..9e4f22d 100644 --- a/include/cbdutil.h +++ b/include/cbdutil.h @@ -43,8 +43,8 @@ int verbose(uint level, const char* fmt, ...); bool ask_user_bool(tristate_t auto_response, const char* fmt, ...); -void pblk_read(int fd, u32 pblk_size, u64 pblk, u32 count, u8* data); -void pblk_write(int fd, u32 pblk_size, u64 pblk, u32 count, const u8* data); +void pblk_read(int fd, u64 pblk, u32 count, u8* data); +void pblk_write(int fd, u64 pblk, u32 count, const u8* data); void cbd_check_header(const struct cbd_header* header); diff --git a/include/libcbd.h b/include/libcbd.h index 91f6e64..f2af8dd 100644 --- a/include/libcbd.h +++ b/include/libcbd.h @@ -25,6 +25,13 @@ #define PAGE_SIZE (1 << PAGE_SHIFT) #endif +#ifndef PBLK_SHIFT +#define PBLK_SHIFT 12 +#endif +#ifndef PBLK_SIZE +#define PBLK_SIZE (1 << PBLK_SHIFT) +#endif + #ifndef min #define min(a, b) ((a) < (b) ? (a) : (b)) #endif @@ -54,8 +61,7 @@ typedef uint64_t u64; #include -#define CBD_DEFAULT_COMPRESSION_FACTOR 2.0 -#define CBD_DEFAULT_PHYSICAL_BLOCK_SHIFT 3 +#define CBD_DEFAULT_COMPRESSION_FACTOR 1.5 #define CBD_DEFAULT_LOGICAL_BLOCK_SHIFT 4 /* XXX: move to types.h */ @@ -68,8 +74,7 @@ typedef enum { int cbd_format(const char* dev, uint16_t flags, enum cbd_alg alg, uint level, - uint8_t pshift, uint8_t lshift, - uint8_t pbatshift, + uint8_t lshift, uint64_t psize, uint64_t lsize, bool full_init); int cbd_open(const char* dev, diff --git a/include/linux/dm-compress.h b/include/linux/dm-compress.h index e103f21..9dfdec3 100644 --- a/include/linux/dm-compress.h +++ b/include/linux/dm-compress.h @@ -1,12 +1,13 @@ #ifndef _LINUX_DM_COMPRESS_H #define _LINUX_DM_COMPRESS_H -#define PBLK_SHIFT_MIN 0 -#define PBLK_SHIFT_MAX 3 +#define PBLK_SHIFT 12 +#define PBLK_SIZE (1 << PBLK_SHIFT) +#define PBLK_SIZE_BITS (PBLK_SIZE * BITS_PER_BYTE) +#define PBLK_PER_SECTOR (1 << (PBLK_SHIFT - SECTOR_SHIFT)) + #define LBLK_SHIFT_MIN 1 #define LBLK_SHIFT_MAX 10 -#define PBAT_SHIFT_MIN 0 -#define PBAT_SHIFT_MAX 3 #define ZONE_NONE (u32)(~0) #define PBLK_NONE (u64)(~0) @@ -35,11 +36,9 @@ enum cbd_alg { struct cbd_params { u16 flags; u8 compression; /* alg and level */ - u8 pblk_shift; u8 lblk_shift; u8 lba_elem_pblk_bytes; - u8 pbat_shift; - /* u8 pad */ + /* u8 pad[3] */ u32 nr_zones; u32 lblk_per_zone; u32 init_zones; @@ -231,16 +230,10 @@ cbd_bitmap_isset(u8* buf, u32 idx) -static inline u32 -pblk_size(const struct cbd_params* params) -{ - return (1 << params->pblk_shift) * SECTOR_SIZE; -} - static inline u32 pblk_size_bits(const struct cbd_params* params) { - return pblk_size(params) * BITS_PER_BYTE; + return PBLK_SIZE * BITS_PER_BYTE; } static inline u32 @@ -252,13 +245,7 @@ lblk_per_pblk(const struct cbd_params* params) static inline u32 lblk_size(const struct cbd_params* params) { - return pblk_size(params) * lblk_per_pblk(params); -} - -static inline u32 -pbat_len(const struct cbd_params* params) -{ - return (1 << params->pbat_shift); + return PBLK_SIZE * lblk_per_pblk(params); } static inline u32 @@ -283,20 +270,19 @@ lba_len(const struct cbd_params* params) static inline u32 lbat_len(const struct cbd_params* params) { - return DIV_ROUND_UP(params->lblk_per_zone * lba_len(params), pblk_size(params)); + return DIV_ROUND_UP(params->lblk_per_zone * lba_len(params), PBLK_SIZE); } static inline u32 zone_metadata_len(const struct cbd_params* params) { - return pbat_len(params) + - lbat_len(params); + return 1 + lbat_len(params); } static inline u32 zone_data_len(const struct cbd_params* params) { - return pbat_len(params) * pblk_size(params) * BITS_PER_BYTE; + return PBLK_SIZE * BITS_PER_BYTE; } static inline u32 @@ -321,16 +307,13 @@ pbat_off(const struct cbd_params* params, u32 idx) static inline u64 lbat_off(const struct cbd_params* params, u32 idx) { - return zone_off(params, idx) + - pbat_len(params); + return zone_off(params, idx) + 1; } static inline u64 zone_data_off(const struct cbd_params* params, u32 idx) { - return zone_off(params, idx) + - pbat_len(params) + - lbat_len(params); + return lbat_off(params, idx) + lbat_len(params); } static inline u32 @@ -358,11 +341,9 @@ cbd_header_get(const u8* buf, struct cbd_header* header) header->version_minor = get16_le(&p); header->params.flags = get16_le(&p); header->params.compression = get_byte(&p); - header->params.pblk_shift = get_byte(&p); header->params.lblk_shift = get_byte(&p); header->params.lba_elem_pblk_bytes = get_byte(&p); - header->params.pbat_shift = get_byte(&p); - p += 1; /* pad */ + p += 3; /* pad */ header->params.nr_zones = get32_le(&p); header->params.lblk_per_zone = get32_le(&p); header->params.init_zones = get32_le(&p); @@ -381,10 +362,10 @@ cbd_header_put(u8* buf, const struct cbd_header* header) put16_le(&p, header->version_minor); put16_le(&p, header->params.flags); put_byte(&p, header->params.compression); - put_byte(&p, header->params.pblk_shift); put_byte(&p, header->params.lblk_shift); put_byte(&p, header->params.lba_elem_pblk_bytes); - put_byte(&p, header->params.pbat_shift); + put_byte(&p, 0); /* pad */ + put_byte(&p, 0); /* pad */ put_byte(&p, 0); /* pad */ put32_le(&p, header->params.nr_zones); put32_le(&p, header->params.lblk_per_zone); @@ -588,15 +569,15 @@ void cbd_free_pagev(struct page** pagev, size_t len); /* Core low-level I/O */ #define PBLK_IOV_MAX (PAGE_SIZE / SECTOR_SIZE) int pblk_read_wait(struct compress_params* kparams, - u64 pblk, u32 count, struct page* page); + u64 pblk, struct page* page); int pblk_readv_wait(struct compress_params* kparams, - u64* pblkv, u32 count, struct page* page); + u64* pblkv, struct page** pagev, u32 count); int pblk_write_wait(struct compress_params* kparams, - u64 pblk, u32 count, struct page* page); + u64 pblk, struct page* page); void pblk_write(struct compress_params* kparams, - u64 pblk, u32 count, struct page* page); + u64 pblk, struct page* page); void pblk_writev(struct compress_params* kparams, - u64* pblkv, u32 count, struct page* page); + u64* pblkv, struct page** pagev, u32 count); struct pbat; u32 pbat_zone(struct pbat* pbat); diff --git a/libcbd/check.c b/libcbd/check.c index 73f52e6..cb12690 100644 --- a/libcbd/check.c +++ b/libcbd/check.c @@ -24,25 +24,25 @@ struct check_state static void pbat_read(int fd, const struct cbd_params* params, u32 zone, u8* data) { - pblk_read(fd, pblk_size(params), pbat_off(params, zone), pbat_len(params), data); + pblk_read(fd, pbat_off(params, zone), 1, data); } static void pbat_write(int fd, const struct cbd_params* params, u32 zone, const u8* data) { - pblk_write(fd, pblk_size(params), pbat_off(params, zone), pbat_len(params), data); + pblk_write(fd, pbat_off(params, zone), 1, data); } static void lbat_read(int fd, const struct cbd_params* params, u32 zone, u8* data) { - pblk_read(fd, pblk_size(params), lbat_off(params, zone), lbat_len(params), data); + pblk_read(fd, lbat_off(params, zone), lbat_len(params), data); } static void lbat_write(int fd, const struct cbd_params* params, u32 zone, const u8* data) { - pblk_write(fd, pblk_size(params), lbat_off(params, zone), lbat_len(params), data); + pblk_write(fd, lbat_off(params, zone), lbat_len(params), data); } static bool @@ -119,16 +119,16 @@ check_lblk_data(struct check_state* state, u32 n; u64 pblk; - data = calloc(pblk_size(params), lblk_per_pblk(params)); + data = calloc(PBLK_SIZE, lblk_per_pblk(params)); buf = lba; len = lba_len_get(params, buf); if (len == 0 || len == CBD_UNCOMPRESSED) { return true; } - n_alloc = DIV_ROUND_UP(len, pblk_size(params)); + n_alloc = DIV_ROUND_UP(len, PBLK_SIZE); for (n = 0; n < n_alloc; ++n) { pblk = lba_pblk_get(params, buf, n); - pblk_read(state->fd, pblk_size(params), pblk, 1, data + n * pblk_size(params)); + pblk_read(state->fd, pblk, 1, data + n * PBLK_SIZE); } ret = check_decompress(state, params, data, len); free(data); @@ -179,7 +179,7 @@ check_lblk_alloc(struct check_state* state, } n_alloc = (len == CBD_UNCOMPRESSED) ? lblk_per_pblk(params) : - DIV_ROUND_UP(len, pblk_size(params)); + DIV_ROUND_UP(len, PBLK_SIZE); for (n = 0; n < n_alloc; ++n) { pblk = lba_pblk_get(params, buf, n); if (pblk < CBD_HEADER_BLOCKS) { @@ -239,7 +239,7 @@ check_lbat(struct check_state* state, const struct cbd_params* params) u32 zone; for (zone = 0; zone < params->init_zones; ++zone) { - u8* lbat = calloc(pblk_size(params), lbat_len(params)); + u8* lbat = calloc(PBLK_SIZE, lbat_len(params)); bool zone_empty = true; bool changed = false; u32 n; @@ -288,14 +288,14 @@ check_pbat(struct check_state* state, const struct cbd_params* params) u32 zone; u8* pbat; - pbat = malloc(pblk_size(params) * pbat_len(params)); + pbat = malloc(PBLK_SIZE); for (zone = 0; zone < params->init_zones; ++zone) { bool changed = false; pbat_read(state->fd, params, zone, pbat); - if (memcmp(pbat, state->pbatv[zone], pblk_size(params) * pbat_len(params)) != 0) { + if (memcmp(pbat, state->pbatv[zone], PBLK_SIZE) != 0) { if (ask_user_bool(state->auto_response, "zone %u has incorrect pbat. Fix?", zone)) { - memcpy(pbat, state->pbatv[zone], pblk_size(params) * pbat_len(params)); + memcpy(pbat, state->pbatv[zone], PBLK_SIZE); changed = true; } else { @@ -317,7 +317,7 @@ cbd_check(const char* dev, { struct check_state state; struct cbd_header header; - uint8_t buf[SECTOR_SIZE]; + uint8_t buf[PBLK_SIZE]; u32 n; memset(&state, 0, sizeof(state)); @@ -327,7 +327,7 @@ cbd_check(const char* dev, } verbose(1, "Reading header\n"); - pblk_read(state.fd, SECTOR_SIZE, 0, 1, buf); + pblk_read(state.fd, 0, 1, buf); cbd_header_get(buf, &header); verbose(1, "Checking header\n"); cbd_check_header(&header); @@ -346,7 +346,7 @@ cbd_check(const char* dev, state.clean = true; state.pbatv = calloc(header.params.nr_zones, sizeof(u8*)); for (n = 0; n < header.params.nr_zones; ++n) { - state.pbatv[n] = calloc(pblk_size(&header.params), pbat_len(&header.params)); + state.pbatv[n] = calloc(PBLK_SIZE, 1); } if (full_check) { state.compress_buf = malloc(lblk_size(&header.params)); @@ -381,7 +381,7 @@ cbd_check(const char* dev, } header.params.flags &= ~(CBD_FLAG_ERROR | CBD_FLAG_DIRTY); cbd_header_put(buf, &header); - pblk_write(state.fd, SECTOR_SIZE, 0, 1, buf); + pblk_write(state.fd, 0, 1, buf); } close(state.fd); diff --git a/libcbd/format.c b/libcbd/format.c index abafc05..196e361 100644 --- a/libcbd/format.c +++ b/libcbd/format.c @@ -9,13 +9,11 @@ int cbd_format(const char* dev, uint16_t flags, enum cbd_alg alg, uint level, - uint8_t pshift, uint8_t lshift, - uint8_t pbatshift, + uint8_t lshift, uint64_t psize, uint64_t lsize, bool full_init) { int fd; - uint pblk_size; uint lblk_size; uint32_t est_zone_len; struct cbd_header header; @@ -35,14 +33,6 @@ cbd_format(const char* dev, if (level < 1 || level > 9) { error("Compression level %u out of bounds\n", level); } - if (!pshift) { - pshift = CBD_DEFAULT_PHYSICAL_BLOCK_SHIFT; - } - if (pshift < PBLK_SHIFT_MIN || pshift > PBLK_SHIFT_MAX) { - error("Physical block shift %u is not in [%u,%u]\n", - (uint)pshift, (uint)PBLK_SHIFT_MIN, (uint)PBLK_SHIFT_MAX); - } - pblk_size = SECTOR_SIZE * (1 << pshift); if (!lshift) { lshift = CBD_DEFAULT_LOGICAL_BLOCK_SHIFT; } @@ -50,21 +40,17 @@ cbd_format(const char* dev, error("Logical block shift %u is not in [%u,%u]\n", (uint)lshift, (uint)LBLK_SHIFT_MIN, (uint)LBLK_SHIFT_MAX); } - lblk_size = pblk_size * (1 << lshift); - if (pbatshift < PBAT_SHIFT_MIN || pbatshift > PBAT_SHIFT_MAX) { - error("Physical block allocation table shift %u is not in [%u,%u]\n", - (uint)pbatshift, (uint)PBAT_SHIFT_MIN, (uint)PBAT_SHIFT_MAX); - } + lblk_size = PBLK_SIZE * (1 << lshift); if (!psize) { off_t pos; pos = lseek(fd, 0, SEEK_END); if (pos == (off_t)-1) { error("Cannot seek device\n"); } - psize = pos / pblk_size * pblk_size; + psize = pos / PBLK_SIZE * PBLK_SIZE; } - if (psize % pblk_size) { - error("Physical size %lu is not a multiple of %u bytes\n", (ulong)psize, pblk_size); + if (psize % PBLK_SIZE) { + error("Physical size %lu is not a multiple of %u bytes\n", (ulong)psize, PBLK_SIZE); } if (!lsize) { /* XXX: Why is the cast needed here? */ @@ -75,9 +61,7 @@ cbd_format(const char* dev, } printf("%s: parameters...\n", __func__); - printf(" pshift=%u\n", (unsigned int)pshift); printf(" lshift=%u\n", (unsigned int)lshift); - printf(" pbatshift=%u\n", (unsigned int)pbatshift); printf(" alg=%d\n", (int)alg); printf(" level=%u\n", level); printf(" psize=%lu\n", (unsigned long)psize); @@ -90,22 +74,17 @@ cbd_format(const char* dev, header.params.compression = 0; cbd_compression_alg_put(&header.params, alg); cbd_compression_level_put(&header.params, level); - header.params.pblk_shift = pshift; header.params.lblk_shift = lshift; header.params.lba_elem_pblk_bytes = - ((psize / pblk_size) <= 0xffff ? 2 : - ((psize / pblk_size) <= 0xffffffff ? 4 : 6)); - header.params.pbat_shift = pbatshift; - if (pbat_len(&header.params) * pblk_size > PAGE_SIZE) { - error("Physical block allocation table too large\n"); - } - if (lba_len(&header.params) > pblk_size) { + ((psize / PBLK_SIZE) <= 0xffff ? 2 : + ((psize / PBLK_SIZE) <= 0xffffffff ? 4 : 6)); + if (lba_len(&header.params) > PBLK_SIZE) { error("lba element size too large\n"); } /* XXX: Initial estimate */ - header.params.lblk_per_zone = zone_data_len(&header.params) * (lsize / lblk_size) / (psize / pblk_size); + header.params.lblk_per_zone = zone_data_len(&header.params) * (lsize / lblk_size) / (psize / PBLK_SIZE); printf(" initial estimate for lblk_per_zone: %u\n", (unsigned int)header.params.lblk_per_zone); - header.params.nr_zones = ((psize / pblk_size) - CBD_HEADER_BLOCKS) / zone_len(&header.params); + header.params.nr_zones = ((psize / PBLK_SIZE) - CBD_HEADER_BLOCKS) / zone_len(&header.params); est_zone_len = zone_len(&header.params); header.params.lblk_per_zone = DIV_ROUND_UP(lsize / lblk_size, header.params.nr_zones); while (zone_len(&header.params) > est_zone_len) { @@ -114,16 +93,14 @@ cbd_format(const char* dev, header.params.init_zones = 0; printf("%s: header...\n", __func__); printf(" compression=0x%02x\n", (unsigned int)header.params.compression); - printf(" pblk_shift=%hu\n", (unsigned short)header.params.pblk_shift); printf(" lblk_shift=%hu\n", (unsigned short)header.params.lblk_shift); printf(" lba_elem_pblk_bytes=%hu\n", (unsigned short)header.params.lba_elem_pblk_bytes); - printf(" pbat_shift=%hu\n", (unsigned short)header.params.pbat_shift); printf(" nr_zones=%u\n", (unsigned int)header.params.nr_zones); printf(" lblk_per_zone=%u\n", (unsigned int)header.params.lblk_per_zone); memset(header_buf, 0, sizeof(header_buf)); cbd_header_put(header_buf, &header); - pblk_write(fd, pblk_size, 0, 1, header_buf); + pblk_write(fd, 0, 1, header_buf); if (full_init) { uint32_t nr_pblk = zone_metadata_len(&header.params); @@ -134,24 +111,24 @@ cbd_format(const char* dev, printf("Writing %lu zones ...\n", (unsigned long)header.params.nr_zones); - data_buf = calloc(nr_pblk, pblk_size); + data_buf = calloc(nr_pblk, PBLK_SIZE); next_write = time(NULL) + 5; while (header.params.init_zones < header.params.nr_zones) { pblk = zone_off(&header.params, header.params.init_zones); - pblk_write(fd, pblk_size, pblk, nr_pblk, data_buf); + pblk_write(fd, pblk, nr_pblk, data_buf); ++header.params.init_zones; now = time(NULL); if (now >= next_write) { printf("Initialized %u/%u zones\n", header.params.init_zones, header.params.nr_zones); cbd_header_put(header_buf, &header); - pblk_write(fd, pblk_size, 0, 1, header_buf); + pblk_write(fd, 0, 1, header_buf); next_write = now + 5; } } free(data_buf); cbd_header_put(header_buf, &header); - pblk_write(fd, pblk_size, 0, 1, header_buf); + pblk_write(fd, 0, 1, header_buf); } return 0; diff --git a/libcbd/open.c b/libcbd/open.c index 229213c..88350d4 100644 --- a/libcbd/open.c +++ b/libcbd/open.c @@ -8,7 +8,7 @@ static uint64_t device_logical_sectors(const char* dev) { int fd; - uint8_t buf[SECTOR_SIZE]; + uint8_t buf[PBLK_SIZE]; struct cbd_header header; uint64_t lblk_total; @@ -26,7 +26,7 @@ device_logical_sectors(const char* dev) } lblk_total = header.params.lblk_per_zone * header.params.nr_zones; - return lblk_total << (header.params.lblk_shift + header.params.pblk_shift); + return lblk_total << (header.params.lblk_shift + (PBLK_SHIFT - SECTOR_SHIFT)); } int diff --git a/libcbd/stats.c b/libcbd/stats.c index c95c785..cb3118c 100644 --- a/libcbd/stats.c +++ b/libcbd/stats.c @@ -6,7 +6,7 @@ int cbd_stats(const char* dev, struct cbd_stats* stats) { int fd; - uint8_t buf[SECTOR_SIZE]; + uint8_t buf[PBLK_SIZE]; struct cbd_header header; fd = open(dev, O_RDONLY); diff --git a/libcbd/tune.c b/libcbd/tune.c index 064e842..f59d66c 100644 --- a/libcbd/tune.c +++ b/libcbd/tune.c @@ -9,14 +9,14 @@ cbd_tune(const char* dev, tristate_t zero_detect, uint level, bool repack) { int fd; - uint8_t header_buf[SECTOR_SIZE]; + uint8_t header_buf[PBLK_SIZE]; struct cbd_header header; fd = open(dev, O_RDWR); if (fd < 0) { error("Cannot open device"); } - pblk_read(fd, SECTOR_SIZE, 0, 1, header_buf); + pblk_read(fd, 0, 1, header_buf); cbd_header_get(header_buf, &header); cbd_check_header(&header); @@ -32,7 +32,7 @@ cbd_tune(const char* dev, cbd_compression_level_put(&header.params, level); } cbd_header_put(header_buf, &header); - pblk_write(fd, SECTOR_SIZE, 0, 1, header_buf); + pblk_write(fd, 0, 1, header_buf); if (repack) { error("repack not supported yet\n"); diff --git a/libcbd/util.c b/libcbd/util.c index 649a002..96f9b22 100644 --- a/libcbd/util.c +++ b/libcbd/util.c @@ -74,18 +74,18 @@ again: } void -pblk_read(int fd, u32 pblk_size, u64 pblk, u32 count, u8* data) +pblk_read(int fd, u64 pblk, u32 count, u8* data) { off_t pos; size_t remain; ssize_t ret; - pos = lseek(fd, pblk * pblk_size, SEEK_SET); + pos = lseek(fd, pblk * PBLK_SIZE, SEEK_SET); if (pos == (off_t)-1) { error("Failed to seek\n"); } - remain = count * pblk_size; + remain = count * PBLK_SIZE; while (remain) { ret = read(fd, data, remain); if (ret <= 0) { @@ -97,18 +97,18 @@ pblk_read(int fd, u32 pblk_size, u64 pblk, u32 count, u8* data) } void -pblk_write(int fd, u32 pblk_size, u64 pblk, u32 count, const u8* data) +pblk_write(int fd, u64 pblk, u32 count, const u8* data) { off_t pos; size_t remain; ssize_t ret; - pos = lseek(fd, pblk * pblk_size, SEEK_SET); + pos = lseek(fd, pblk * PBLK_SIZE, SEEK_SET); if (pos == (off_t)-1) { error("Failed to seek\n"); } - remain = count * pblk_size; + remain = count * PBLK_SIZE; while (remain) { ret = write(fd, data, remain); if (ret <= 0) {