Remove variable pblk and pbat sizes, optimize, and cleanup

This commit is contained in:
Tom Marshall 2021-05-15 11:24:56 -07:00
parent 2fab692cdf
commit 9ff7a1ddaf
17 changed files with 210 additions and 370 deletions

37
README
View File

@ -2,7 +2,7 @@ This is a device mapper block compression driver.
Note: Note:
- Sectors are always 512 bytes (kernel constant). - Sectors are always 512 bytes (kernel constant).
- Physical blocks are variable 512b .. 4kb. - Physical blocks are always 4kb.
- Logical blocks are variable 4kb .. 4mb. - Logical blocks are variable 4kb .. 4mb.
- All integers are little endian. - All integers are little endian.
@ -17,11 +17,9 @@ Block device layout:
- u8 compression - u8 compression
hi nybble: algorithm (1=lz4, 2=zlib, ...) [1] hi nybble: algorithm (1=lz4, 2=zlib, ...) [1]
lo nybble: level (1..9) [1] lo nybble: level (1..9) [1]
- u8 pblk_shift (0..3) [3 = 4kb]
- u8 lblk_shift (1..10) [4 = 64kb (*)] - u8 lblk_shift (1..10) [4 = 64kb (*)]
- u8 lba_elem_pblk_bytes (2, 4, 6) - u8 lba_elem_pblk_bytes (2, 4, 6)
- u8 pbat_shift [0] - u8[3] pad
- u8 pad
- u32 nr_zones - u32 nr_zones
- u32 lblk_per_zone - u32 lblk_per_zone
- byte[40] reserved - byte[40] reserved
@ -33,9 +31,8 @@ Block device layout:
- byte[384] reserved - byte[384] reserved
- pblk[] zone ... vector of zone - pblk[] zone ... vector of zone
(*) The maximum lblk_shift may be (and usually is) less than 10 because (*) The maximum lblk_shift may be less than 10 because lblk_alloc size
lblk_alloc size must be <= pblk size. When pblk_shift=1 (1024) and must be <= pblk size.
lblk_alloc_16_32, the maximum lblk_shift is 8 (256kb).
Device size limits: Device size limits:
- Min: header plus one zone (header, pbat, lbat, data) - Min: header plus one zone (header, pbat, lbat, data)
@ -43,19 +40,19 @@ Device size limits:
- Max: 2^48 pblk = 1eb - Max: 2^48 pblk = 1eb
There are six different lblk_alloc sizes: There are six different lblk_alloc sizes:
Struct name Size lblk_size device_pblk_size Struct name Size lblk_shift lblk_size device pblks
=========== ==== ========= ================ =========== ===== ========== ========= ============
lblk_alloc_16_16 2+2*8 <= 64kb <= 64k lblk_alloc_16_16 2+2*n 1..10 <= 64kb <= 64k
lblk_alloc_16_32 2+4*8 <= 64kb <= 4g lblk_alloc_16_32 2+4*n 1..9 <= 64kb <= 4g
lblk_alloc_16_48 2+6*8 <= 64kb <= 256t lblk_alloc_16_48 2+6*n 1..9 <= 64kb <= 256t
lblk_alloc_32_16 4+2*8 > 64kb <= 64k lblk_alloc_32_16 4+2*n 1..10 > 64kb <= 64k
lblk_alloc_32_32 4+4*8 > 64kb <= 4g lblk_alloc_32_32 4+4*n 1..9 > 64kb <= 4g
lblk_alloc_32_48 4+6*8 > 64kb <= 256t lblk_alloc_32_48 4+6*n 1..9 > 64kb <= 256t
Zone layout: Zone layout:
- byte[pblk_size*pbat_len] Physical block allocation table (pbat) - byte[pblk_size] Physical block allocation table (pbat)
- lblk_alloc_x_y[] Logical block allocation table (lbat) - lblk_alloc_x_y[] Logical block allocation table (lbat)
Note: padded to pblk size Note: padded to pblk size
- data[] Data - data[] Data
One pblk per bit in pbat One pblk per bit in pbat

View File

@ -93,21 +93,20 @@ parse_boolean_arg(const char* arg, uint64_t* val)
struct profile { struct profile {
const char* name; const char* name;
uint pblksize;
uint lblksize; uint lblksize;
enum cbd_alg alg; enum cbd_alg alg;
uint level; uint level;
}; };
static struct profile profiles[] = { static struct profile profiles[] = {
{ "performance", 1*1024, 4*1024, CBD_ALG_LZ4, 1 }, { "performance", 4*1024, CBD_ALG_LZ4, 1 },
{ "mixed", 4*1024, 64*1024, CBD_ALG_LZ4, 3 }, { "mixed", 64*1024, CBD_ALG_LZ4, 3 },
{ "read-mostly", 4*1024, 64*1024, CBD_ALG_ZLIB, 6 }, { "read-mostly", 64*1024, CBD_ALG_ZLIB, 6 },
{ "archive", 4*1024, 256*1024, CBD_ALG_ZLIB, 9 }, { "archive", 256*1024, CBD_ALG_ZLIB, 9 },
}; };
static bool static bool
parse_profile(const char* name, parse_profile(const char* name,
uint* pblksize, uint* lblksize, uint* lblksize,
enum cbd_alg* alg, uint* level) enum cbd_alg* alg, uint* level)
{ {
uint n; uint n;
@ -115,7 +114,6 @@ parse_profile(const char* name,
for (n = 0; n < ARRAY_SIZE(profiles); ++n) { for (n = 0; n < ARRAY_SIZE(profiles); ++n) {
struct profile* profile = &profiles[n]; struct profile* profile = &profiles[n];
if (!strcmp(profile->name, name)) { if (!strcmp(profile->name, name)) {
*pblksize = profile->pblksize;
*lblksize = profile->lblksize; *lblksize = profile->lblksize;
*alg = profile->alg; *alg = profile->alg;
*level = profile->level; *level = profile->level;
@ -152,12 +150,10 @@ usage(void)
"\n"); "\n");
fprintf(stderr, "Commands:\n" fprintf(stderr, "Commands:\n"
" format [opts] <device> Create (format) a compressed device\n" " format [opts] <device> Create (format) a compressed device\n"
" -P --pbat-size Physical block allocation table size [1]\n"
" -S --pysical-size Physical size [device size]\n" " -S --pysical-size Physical size [device size]\n"
" -Z --compress-level Compression level [1]\n" " -Z --compress-level Compression level [1]\n"
" -c --compress-factor Compression factor [2.0]\n" " -c --compress-factor Compression factor [2.0]\n"
" -l --logical-blksize Logical block size\n" " -l --logical-blksize Logical block size\n"
" -p --physical-blksize Physical block size\n"
" -s --size Logical size\n" " -s --size Logical size\n"
" -z --compress-alg Compression algorithm [lz4]\n" " -z --compress-alg Compression algorithm [lz4]\n"
" --detect-zeros Detect and free zero blocks at runtime\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" " -c and -s are different ways of specifying the compressed device size.\n"
" Only one may be used, not both.\n" " Only one may be used, not both.\n"
" Profiles:\n" " Profiles:\n"
" performance: 1k pblk, 4k lblk, lz4 level 1\n" " performance: 4k lblk, lz4 level 1\n"
" mixed: 4k pblk, 64k lblk, lz4 level 3\n" " mixed: 64k lblk, lz4 level 3\n"
" read-mostly: 4k pblk, 64k lblk, zlib level 6\n" " read-mostly: 64k lblk, zlib level 6\n"
" archive: 4k pblk, 256k lblk, zlib level 9\n" " archive: 256k lblk, zlib level 9\n"
"\n" "\n"
" open [opts] <device> <name> Open an existing compressed device\n" " open [opts] <device> <name> Open an existing compressed device\n"
" -c --cache-pages Set cache pages\n" " -c --cache-pages Set cache pages\n"
@ -202,14 +198,12 @@ usage(void)
static int static int
do_format(int argc, char** argv) 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[] = { static const struct option long_opts[] = {
{ "pbat-size", required_argument, NULL, 'P' },
{ "physical-size", required_argument, NULL, 'S' }, { "physical-size", required_argument, NULL, 'S' },
{ "compress-level", required_argument, NULL, 'Z' }, { "compress-level", required_argument, NULL, 'Z' },
{ "compress-factor", required_argument, NULL, 'c' }, { "compress-factor", required_argument, NULL, 'c' },
{ "logical-blksize", required_argument, NULL, 'l' }, { "logical-blksize", required_argument, NULL, 'l' },
{ "physical-blksize", required_argument, NULL, 'p' },
{ "size", required_argument, NULL, 's' }, { "size", required_argument, NULL, 's' },
{ "compress-alg", required_argument, NULL, 'z' }, { "compress-alg", required_argument, NULL, 'z' },
{ "detect-zeros", optional_argument, NULL, 0x1 }, { "detect-zeros", optional_argument, NULL, 0x1 },
@ -221,31 +215,18 @@ do_format(int argc, char** argv)
uint64_t optval; uint64_t optval;
uint64_t psize = 0; uint64_t psize = 0;
uint64_t lsize = 0; uint64_t lsize = 0;
uint pblksize = PAGE_SIZE;
uint lblksize = 16 * PAGE_SIZE; uint lblksize = 16 * PAGE_SIZE;
uint pbatsize = 1;
uint16_t flags = 0; uint16_t flags = 0;
enum cbd_alg alg = CBD_ALG_LZ4; enum cbd_alg alg = CBD_ALG_LZ4;
uint level = 1; uint level = 1;
bool full_init = false; bool full_init = false;
uint8_t pshift;
uint8_t lshift; uint8_t lshift;
uint8_t pbatshift;
const char* dev; const char* dev;
while ((opt = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) { while ((opt = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
switch (opt) { 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': case 'S':
if (!parse_numeric_arg(optarg, &optval)) { if (!parse_numeric_arg(optarg, &optval)) {
error("Failed to parse \"%s\"\n", optarg); error("Failed to parse \"%s\"\n", optarg);
@ -273,15 +254,6 @@ do_format(int argc, char** argv)
} }
lblksize = optval; lblksize = optval;
break; 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': case 's':
if (!parse_numeric_arg(optarg, &optval)) { if (!parse_numeric_arg(optarg, &optval)) {
error("Failed to parse \"%s\"\n", optarg); error("Failed to parse \"%s\"\n", optarg);
@ -312,7 +284,7 @@ do_format(int argc, char** argv)
} }
break; break;
case 0x2: case 0x2:
if (!parse_profile(optarg, &pblksize, &lblksize, &alg, &level)) { if (!parse_profile(optarg, &lblksize, &alg, &level)) {
error("Invalid profile \"%s\"\n", optarg); error("Invalid profile \"%s\"\n", optarg);
} }
break; break;
@ -323,25 +295,17 @@ do_format(int argc, char** argv)
usage(); usage();
} }
} }
pshift = get_shift(pblksize, SECTOR_SIZE); lshift = get_shift(lblksize, PBLK_SIZE);
if (pshift < PBLK_SHIFT_MIN || pshift > PBLK_SHIFT_MAX) {
error("Invalid physical block size %u\n", pblksize);
}
lshift = get_shift(lblksize, pblksize);
if (lshift < LBLK_SHIFT_MIN || lshift > LBLK_SHIFT_MAX) { if (lshift < LBLK_SHIFT_MIN || lshift > LBLK_SHIFT_MAX) {
error("Invalid logical block size %u\n", lblksize); 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) { if (argc - optind != 1) {
usage(); usage();
} }
dev = argv[optind++]; dev = argv[optind++];
cbd_format(dev, flags, alg, level, cbd_format(dev, flags, alg, level,
pshift, lshift, pbatshift, psize, lsize, lshift, psize, lsize,
full_init); full_init);
return 0; return 0;

View File

@ -71,15 +71,15 @@ blkdev_pages(struct block_device* bdev)
} }
static inline u64 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 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 static inline u64
@ -107,7 +107,7 @@ compress_read_header(struct compress* c, char** errorp)
} }
buf = page_address(page); buf = page_address(page);
ret = pblk_read_wait(&c->kparams, 0, 1, page); ret = pblk_read_wait(&c->kparams, 0, page);
if (ret) { if (ret) {
*errorp = "Header: failed to read"; *errorp = "Header: failed to read";
goto out; goto out;
@ -156,12 +156,6 @@ compress_read_header(struct compress* c, char** errorp)
ret = -EINVAL; ret = -EINVAL;
goto out; 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 || if (header.params.lblk_shift < LBLK_SHIFT_MIN ||
header.params.lblk_shift > LBLK_SHIFT_MAX) { header.params.lblk_shift > LBLK_SHIFT_MAX) {
*errorp = "Header: lblk_shift out of bounds"; *errorp = "Header: lblk_shift out of bounds";
@ -175,18 +169,7 @@ compress_read_header(struct compress* c, char** errorp)
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
if (header.params.pbat_shift < PBAT_SHIFT_MIN || if (lba_len(&header.params) > PBLK_SIZE) {
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)) {
*errorp = "Header: lba elem size too large"; *errorp = "Header: lba elem size too large";
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
@ -199,10 +182,8 @@ compress_read_header(struct compress* c, char** errorp)
printk(KERN_INFO "%s: parameters...\n", __func__); printk(KERN_INFO "%s: parameters...\n", __func__);
printk(KERN_INFO " compression=0x%02x\n", (unsigned int)header.params.compression); 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 " 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 " 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 " 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 " lblk_per_zone=%u\n", (unsigned int)header.params.lblk_per_zone);
printk(KERN_INFO "%s: stats...\n", __func__); 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.params, &c->kparams.params, sizeof(header.params));
memcpy(&header.stats, &c->kstats.stats, sizeof(header.stats)); memcpy(&header.stats, &c->kstats.stats, sizeof(header.stats));
cbd_header_put(buf, &header); cbd_header_put(buf, &header);
ret = pblk_write_wait(&c->kparams, 0, 1, page); ret = pblk_write_wait(&c->kparams, 0, page);
if (ret) { if (ret) {
printk(KERN_ERR "%s: failed to write header\n", __func__); printk(KERN_ERR "%s: failed to write header\n", __func__);
} }
@ -263,21 +244,12 @@ compress_write_header_dirty(struct compress* c)
static void static void
init_zone(struct compress* c, u32 zone, struct page* page) 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); u64 zone_pblk = zone_off(&c->kparams.params, zone);
u32 nr_pblk = zone_metadata_len(&c->kparams.params); u32 nr_pblk = zone_metadata_len(&c->kparams.params);
u32 pblk_idx; u32 pblk_idx;
u64 pblkv[PBLK_IOV_MAX];
u32 iov_len;
u32 n;
pblk_idx = 0; for (pblk_idx = 0; pblk_idx < nr_pblk; ++pblk_idx) {
while (pblk_idx < nr_pblk) { pblk_write(&c->kparams, zone_pblk + pblk_idx, page);
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);
lock_page(page); lock_page(page);
} }
} }
@ -489,8 +461,7 @@ compress_attr_show(struct kobject* kobj, struct attribute* attr,
val = c->kstats.stats.pblk_used; val = c->kstats.stats.pblk_used;
break; break;
case attr_pblk_total: case attr_pblk_total:
val = pbat_len(&c->kparams.params) * val = pblk_size_bits(&c->kparams.params) *
pblk_size_bits(&c->kparams.params) *
c->kparams.params.nr_zones; c->kparams.params.nr_zones;
break; break;
case attr_lblk_used: case attr_lblk_used:
@ -711,33 +682,33 @@ compress_ctr(struct dm_target *ti, unsigned int argc, char **argv)
/* ti->error already set */ /* ti->error already set */
goto err; 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)) { zone_off(&c->kparams.params, c->kparams.params.nr_zones)) {
printk(KERN_ERR "%s: physical device too small: " printk(KERN_ERR "%s: physical device too small: "
"actual=%lu, needed=%lu\n", __func__, "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)); (unsigned long)zone_off(&c->kparams.params, c->kparams.params.nr_zones));
ti->error = "Physical device too small"; ti->error = "Physical device too small";
ret = -EINVAL; ret = -EINVAL;
goto err; goto err;
} }
if (target_pblks(ti, &c->kparams.params) != if (target_pblks(ti) !=
logical_pblks(&c->kparams.params)) { logical_pblks(&c->kparams.params)) {
printk(KERN_WARNING "%s: incorrect target device size: " printk(KERN_WARNING "%s: incorrect target device size: "
"expected pblks=%lu, actual pblks=%lu\n", __func__, "expected pblks=%lu, actual pblks=%lu\n", __func__,
(unsigned long)logical_pblks(&c->kparams.params), (unsigned long)logical_pblks(&c->kparams.params),
(unsigned long)target_pblks(ti, &c->kparams.params)); (unsigned long)target_pblks(ti));
} }
if (!cache_pages) { if (!cache_pages) {
/* Minimum of 1/1k RAM and 1/64k device size */ /* 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)); (unsigned int)(blkdev_pages(c->dev->bdev) >> 16));
if (cache_pages < 32 * 2 * num_online_cpus()) { if (cache_pages < 32 * 2 * num_online_cpus()) {
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", 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) { if (c->kparams.params.flags & CBD_FLAG_DIRTY) {
printk(KERN_INFO "Warning: device was not properly closed\n"); printk(KERN_INFO "Warning: device was not properly closed\n");

View File

@ -96,7 +96,7 @@ lbatpblk_flush(struct lbatpblk* lp)
ret = -EIO; ret = -EIO;
goto unlock; goto unlock;
} }
pblk_write(lp->kparams, lp->pblk, 1, lp->page); pblk_write(lp->kparams, lp->pblk, lp->page);
mutex_unlock(&lp->lock); mutex_unlock(&lp->lock);
mutex_lock(&lp->kstats->lock); mutex_lock(&lp->kstats->lock);
++lp->kstats->lbatpblk_w; ++lp->kstats->lbatpblk_w;
@ -117,7 +117,7 @@ lbatpblk_read(struct lbatpblk* lp)
int ret = 0; int ret = 0;
BUG_ON(lbatpblk_error(lp)); 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); mutex_lock(&lp->kstats->lock);
++lp->kstats->lbatpblk_r; ++lp->kstats->lbatpblk_r;
mutex_unlock(&lp->kstats->lock); mutex_unlock(&lp->kstats->lock);

View File

@ -263,7 +263,7 @@ lbatview_elem_off(struct lbatview* lv, u64 lblk)
/* The offset of the element in the (full) lbat. */ /* The offset of the element in the (full) lbat. */
u32 lbat_elem_off = zone_rel_lblk * lba_len(&lv->kparams->params); u32 lbat_elem_off = zone_rel_lblk * lba_len(&lv->kparams->params);
/* The offset of the first view pblk. */ /* 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)); (lv->pblk - lbat_off(&lv->kparams->params, lv_zone));
return lbat_elem_off - lbatview_off; return lbat_elem_off - lbatview_off;
@ -272,7 +272,7 @@ lbatview_elem_off(struct lbatview* lv, u64 lblk)
static void static void
lbatview_rmem(struct lbatview* lv, u32 off, u32 len, void* buf) 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); BUG_ON(off + len > 2 * pblk_len);
if (off < pblk_len && off + len > 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 static void
lbatview_wmem(struct lbatview* lv, u32 off, u32 len, void* buf) 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); BUG_ON(off + len > 2 * pblk_len);
if (off < pblk_len && off + len > 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); elem_off = lbatview_elem_off(lv, lblk);
req_nalloc = (len == CBD_UNCOMPRESSED) ? req_nalloc = (len == CBD_UNCOMPRESSED) ?
lblk_per_pblk(&lv->kparams->params) : lblk_per_pblk(&lv->kparams->params) :
DIV_ROUND_UP(len, pblk_size(&lv->kparams->params)); DIV_ROUND_UP(len, PBLK_SIZE);
elem_lelen = 0; elem_lelen = 0;
lbatview_rmem(lv, elem_off, lba_elem_len_bytes(&lv->kparams->params), &elem_lelen); lbatview_rmem(lv, elem_off, lba_elem_len_bytes(&lv->kparams->params), &elem_lelen);
elem_len = __le32_to_cpu(elem_lelen); elem_len = __le32_to_cpu(elem_lelen);
cur_nalloc = (elem_len == CBD_UNCOMPRESSED) ? cur_nalloc = (elem_len == CBD_UNCOMPRESSED) ?
lblk_per_pblk(&lv->kparams->params) : 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; old_nalloc = cur_nalloc;
while (cur_nalloc < req_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); zone_lbat_pblk = lbat_off(lvc->params, zone);
rel_lblk = lblk - lvc->params->lblk_per_zone * zone; rel_lblk = lblk - lvc->params->lblk_per_zone * zone;
lbat_offset = rel_lblk * lba_len(lvc->params); 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; pblk = zone_lbat_pblk + rel_pblk;
count = (rel_pblk == lbat_len(lvc->params) - 1) ? 1 : 2; count = (rel_pblk == lbat_len(lvc->params) - 1) ? 1 : 2;

View File

@ -53,7 +53,7 @@ static inline bool
lblk_is_zeros(struct cbd_params* params, struct lbd* lbd) lblk_is_zeros(struct cbd_params* params, struct lbd* lbd)
{ {
u32 off; 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)) { if (!(params->flags & CBD_FLAG_DETECT_ZEROS)) {
return false; return false;
@ -101,7 +101,7 @@ lblk_compress_lz4(struct lbd* lbd)
clen = LZ4_compress_fast(lbd->buf, state->buf, clen = LZ4_compress_fast(lbd->buf, state->buf,
lblk_size(&lbd->kparams->params), lblk_size(&lbd->kparams->params),
lblk_size(&lbd->kparams->params) - lblk_size(&lbd->kparams->params) -
pblk_size(&lbd->kparams->params), PBLK_SIZE,
cbd_compression_level_get(&lbd->kparams->params), cbd_compression_level_get(&lbd->kparams->params),
state->lz4_workmem); state->lz4_workmem);
if (clen <= 0) { if (clen <= 0) {
@ -159,8 +159,7 @@ lblk_compress_zlib(struct lbd* lbd)
stream->next_in = lbd->buf; stream->next_in = lbd->buf;
stream->avail_in = lblk_size(&lbd->kparams->params); stream->avail_in = lblk_size(&lbd->kparams->params);
stream->next_out = state->buf; stream->next_out = state->buf;
stream->avail_out = lblk_size(&lbd->kparams->params) - stream->avail_out = lblk_size(&lbd->kparams->params) - PBLK_SIZE;
pblk_size(&lbd->kparams->params);
ret = zlib_deflate(stream, Z_FINISH); ret = zlib_deflate(stream, Z_FINISH);
if (ret != Z_STREAM_END) { if (ret != Z_STREAM_END) {
put_cpu(); put_cpu();
@ -337,13 +336,10 @@ lbd_flush(struct lbd* lbd)
{ {
int ret = 0; int ret = 0;
u32 nr_pages = DIV_ROUND_UP(lblk_size(&lbd->kparams->params), PAGE_SIZE); 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; int err;
u32 nr_pblk; u32 nr_pblk;
u32 pblk_idx; u32 pblk_idx;
u32 pg_idx; u64* pblkv;
u64 pblkv[PBLK_IOV_MAX];
u32 iov_len;
u32 n; u32 n;
mutex_lock(&lbd->lock); mutex_lock(&lbd->lock);
@ -362,11 +358,11 @@ lbd_flush(struct lbd* lbd)
} }
lbd->c_len = lblk_compress(lbd); lbd->c_len = lblk_compress(lbd);
if (lbd->c_len > 0) { 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) { if (c_blkrem) {
memset(lbd->buf + lbd->c_len, 0, 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 { else {
lbd->c_len = CBD_UNCOMPRESSED; lbd->c_len = CBD_UNCOMPRESSED;
@ -377,17 +373,16 @@ lbd_flush(struct lbd* lbd)
lbd->kparams->params.flags |= CBD_FLAG_ERROR; lbd->kparams->params.flags |= CBD_FLAG_ERROR;
goto unlock; goto unlock;
} }
for (pblk_idx = 0, pg_idx = 0; pblk_idx < nr_pblk; ++pg_idx) { pblkv = kmalloc(nr_pblk * sizeof(u64), GFP_KERNEL);
iov_len = min(nr_pblk - pblk_idx, pblk_per_page); for (pblk_idx = 0; pblk_idx < nr_pblk; ++pblk_idx) {
for (n = 0; n < iov_len; ++n) { pblkv[pblk_idx] = lbatview_elem_pblk(lbd->lv, lbd->lblk, pblk_idx);
pblkv[n] = lbatview_elem_pblk(lbd->lv, lbd->lblk, pblk_idx++); BUG_ON(pblkv[pblk_idx] == PBLK_NONE);
BUG_ON(pblkv[n] == PBLK_NONE);
}
pblk_writev(lbd->kparams, pblkv, iov_len, lbd->pagev[pg_idx]);
} }
while (pg_idx < nr_pages) { pblk_writev(lbd->kparams, pblkv, lbd->pagev, nr_pblk);
unlock_page(lbd->pagev[pg_idx++]); while (pblk_idx < nr_pages) {
unlock_page(lbd->pagev[pblk_idx++]);
} }
kfree(pblkv);
mutex_lock(&lbd->kstats->lock); mutex_lock(&lbd->kstats->lock);
++lbd->kstats->lbd_w; ++lbd->kstats->lbd_w;
mutex_unlock(&lbd->kstats->lock); mutex_unlock(&lbd->kstats->lock);
@ -413,13 +408,9 @@ static int
lbd_read(struct lbd* lbd) lbd_read(struct lbd* lbd)
{ {
int ret = 0; int ret = 0;
u32 pblk_per_page = PAGE_SIZE / pblk_size(&lbd->kparams->params);
u32 nr_pblk; u32 nr_pblk;
u32 pblk_idx; u32 pblk_idx;
u32 pg_idx; u64* pblkv = NULL;
u64 pblkv[PBLK_IOV_MAX];
u32 iov_len;
u32 n;
BUG_ON(lbd_error(lbd)); BUG_ON(lbd_error(lbd));
lbd->c_len = lbatview_elem_len(lbd->lv, lbd->lblk); lbd->c_len = lbatview_elem_len(lbd->lv, lbd->lblk);
@ -429,28 +420,31 @@ lbd_read(struct lbd* lbd)
else { else {
nr_pblk = (lbd->c_len == CBD_UNCOMPRESSED) ? nr_pblk = (lbd->c_len == CBD_UNCOMPRESSED) ?
lblk_per_pblk(&lbd->kparams->params) : 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)) { if (nr_pblk > lblk_per_pblk(&lbd->kparams->params)) {
printk(KERN_ERR "%s: elem len %u out of range at lblk=%lu\n", printk(KERN_ERR "%s: elem len %u out of range at lblk=%lu\n",
__func__, lbd->c_len, (unsigned long)lbd->lblk); __func__, lbd->c_len, (unsigned long)lbd->lblk);
ret = -EIO; ret = -EIO;
goto out; goto out;
} }
for (pblk_idx = 0, pg_idx = 0; pblk_idx < nr_pblk; ++pg_idx) { pblkv = kmalloc(nr_pblk * sizeof(u64), GFP_KERNEL);
iov_len = min(nr_pblk - pblk_idx, pblk_per_page); if (!pblkv) {
for (n = 0; n < iov_len; ++n) { printk(KERN_ERR "%s: out of memory\n", __func__);
pblkv[n] = lbatview_elem_pblk(lbd->lv, lbd->lblk, pblk_idx++); ret = -EIO;
if (pblkv[n] == PBLK_NONE) { goto out;
printk(KERN_ERR "%s: bad pblk\n", __func__); }
ret = -EIO; for (pblk_idx = 0; pblk_idx < nr_pblk; ++pblk_idx) {
goto out; 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 = pblk_readv_wait(lbd->kparams, pblkv, iov_len, lbd->pagev[pg_idx]); ret = -EIO;
if (ret) {
goto out; goto out;
} }
} }
ret = pblk_readv_wait(lbd->kparams, pblkv, lbd->pagev, nr_pblk);
if (ret) {
goto out;
}
if (lbd->c_len != CBD_UNCOMPRESSED) { if (lbd->c_len != CBD_UNCOMPRESSED) {
if (!lblk_decompress(lbd)) { if (!lblk_decompress(lbd)) {
printk(KERN_ERR "%s: decompress failed\n", __func__); printk(KERN_ERR "%s: decompress failed\n", __func__);
@ -465,6 +459,7 @@ lbd_read(struct lbd* lbd)
mutex_unlock(&lbd->kstats->lock); mutex_unlock(&lbd->kstats->lock);
out: out:
kfree(pblkv);
return ret; return ret;
} }

View File

@ -100,7 +100,7 @@ pbat_flush(struct pbat* pbat)
goto unlock; goto unlock;
} }
pblk = pbat_off(&pbat->kparams->params, pbat->zone); 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_unlock(&pbat->lock);
mutex_lock(&pbat->kstats->lock); mutex_lock(&pbat->kstats->lock);
++pbat->kstats->pbat_w; ++pbat->kstats->pbat_w;
@ -123,7 +123,7 @@ pbat_read(struct pbat* pbat)
BUG_ON(pbat_error(pbat)); BUG_ON(pbat_error(pbat));
pblk = pbat_off(&pbat->kparams->params, pbat->zone); 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); mutex_lock(&pbat->kstats->lock);
++pbat->kstats->pbat_r; ++pbat->kstats->pbat_r;
mutex_unlock(&pbat->kstats->lock); mutex_unlock(&pbat->kstats->lock);
@ -161,8 +161,7 @@ pbat_zone(struct pbat* pbat)
u64 u64
pbat_alloc(struct pbat* pbat) pbat_alloc(struct pbat* pbat)
{ {
u32 bitsize = pblk_size_bits(&pbat->kparams->params) * u32 bitsize = pblk_size_bits(&pbat->kparams->params);
pbat_len(&pbat->kparams->params);
u32 idx; u32 idx;
u64 pblk; u64 pblk;
@ -192,8 +191,7 @@ out:
int int
pbat_free(struct pbat* pbat, u64 pblk) pbat_free(struct pbat* pbat, u64 pblk)
{ {
u32 bitsize = pblk_size_bits(&pbat->kparams->params) * u32 bitsize = pblk_size_bits(&pbat->kparams->params);
pbat_len(&pbat->kparams->params);
u32 zone; u32 zone;
u32 idx; u32 idx;

View File

@ -99,11 +99,10 @@ cbd_free_pagev(struct page** pagev, size_t len)
static struct bio* static struct bio*
pblk_io_prepare(struct block_device* bdev, unsigned int op, 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; struct bio* bio;
BUG_ON(page_off + pblk_len * count > PAGE_SIZE);
bio = bio_alloc(GFP_KERNEL, 1); bio = bio_alloc(GFP_KERNEL, 1);
if (!bio) { if (!bio) {
printk(KERN_ERR "%s: out of memory\n", __func__); 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_set_dev(bio, bdev);
bio->bi_opf = op; bio->bi_opf = op;
bio->bi_iter.bi_sector = pblk * (pblk_len / SECTOR_SIZE); bio->bi_iter.bi_sector = pblk * (PBLK_SIZE / SECTOR_SIZE);
if (bio_add_page(bio, page, pblk_len * count, page_off) == 0) { if (bio_add_page(bio, page, PBLK_SIZE, 0) == 0) {
BUG(); BUG();
} }
return bio; 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 int
pblk_read_wait(struct compress_params* kparams, pblk_read_wait(struct compress_params* kparams,
u64 pblk, u32 count, struct page* page) u64 pblk, struct page* page)
{ {
int ret; int ret;
struct bio* bio; struct bio* bio;
bio = pblk_io_prepare(kparams->dev, REQ_OP_READ, bio = pblk_io_prepare(kparams->dev, REQ_OP_READ, pblk, page);
pblk_size(&kparams->params), pblk, count, page, 0);
if (!bio) { if (!bio) {
printk(KERN_ERR "%s: out of memory\n", __func__); printk(KERN_ERR "%s: out of memory\n", __func__);
return -ENOMEM; return -ENOMEM;
@ -144,28 +158,31 @@ pblk_read_wait(struct compress_params* kparams,
int int
pblk_readv_wait(struct compress_params* kparams, pblk_readv_wait(struct compress_params* kparams,
u64* pblkv, u32 count, struct page* page) u64* pblkv, struct page** pagev, u32 count)
{ {
int ret = 0; int ret = 0;
u32 pblk_len = pblk_size(&kparams->params); u32 idx;
u32 n;
u32 page_off;
struct bio* bio; struct bio* bio;
/* XXX: Issue no-blocking reads for parallelism? */ /* XXX: Issue no-blocking reads for parallelism? */
for (n = 0, page_off = 0; n < count; ++n, page_off += pblk_len) { for (idx = 0; idx < count; ++idx) {
bio = pblk_io_prepare(kparams->dev, REQ_OP_READ, bio = pblk_io_prepare(kparams->dev, REQ_OP_READ, pblkv[idx], pagev[idx]);
pblk_len, pblkv[n], 1, page, page_off);
if (!bio) { if (!bio) {
printk(KERN_ERR "%s: out of memory\n", __func__); printk(KERN_ERR "%s: out of memory\n", __func__);
return -ENOMEM; ret = -ENOMEM;
goto iowait;
} }
ret = submit_bio_wait(bio); bio->bi_end_io = pblk_endio;
if (ret) { bio->bi_private = kparams;
printk(KERN_ERR "%s: submit_bio_wait failed: %d\n", __func__, ret); submit_bio(bio);
return ret; }
iowait:
while (idx > 0) {
--idx;
lock_page(pagev[idx]);
if (PageError(pagev[idx])) {
ret = -EIO;
} }
bio_put(bio);
} }
return ret; return ret;
@ -173,13 +190,12 @@ pblk_readv_wait(struct compress_params* kparams,
int int
pblk_write_wait(struct compress_params* kparams, pblk_write_wait(struct compress_params* kparams,
u64 pblk, u32 count, struct page* page) u64 pblk, struct page* page)
{ {
int ret; int ret;
struct bio* bio; struct bio* bio;
bio = pblk_io_prepare(kparams->dev, REQ_OP_WRITE, bio = pblk_io_prepare(kparams->dev, REQ_OP_WRITE, pblk, page);
pblk_size(&kparams->params), pblk, count, page, 0);
if (!bio) { if (!bio) {
printk(KERN_ERR "%s: out of memory\n", __func__); printk(KERN_ERR "%s: out of memory\n", __func__);
return -ENOMEM; return -ENOMEM;
@ -194,30 +210,13 @@ pblk_write_wait(struct compress_params* kparams,
return ret; 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 void
pblk_write(struct compress_params* kparams, pblk_write(struct compress_params* kparams,
u64 pblk, u32 count, struct page* page) u64 pblk, struct page* page)
{ {
struct bio* bio; struct bio* bio;
bio = pblk_io_prepare(kparams->dev, REQ_OP_WRITE, bio = pblk_io_prepare(kparams->dev, REQ_OP_WRITE, pblk, page);
pblk_size(&kparams->params), pblk, count, page, 0);
if (!bio) { if (!bio) {
printk(KERN_ERR "%s: out of memory\n", __func__); printk(KERN_ERR "%s: out of memory\n", __func__);
kparams->params.flags |= CBD_FLAG_ERROR; kparams->params.flags |= CBD_FLAG_ERROR;
@ -225,65 +224,18 @@ pblk_write(struct compress_params* kparams,
unlock_page(page); unlock_page(page);
return; return;
} }
bio->bi_end_io = pblk_write_endio; bio->bi_end_io = pblk_endio;
bio->bi_private = kparams; bio->bi_private = kparams;
submit_bio(bio); submit_bio(bio);
} }
void void
pblk_writev(struct compress_params* kparams, 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 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); for (idx = 0; idx < count; ++idx) {
parent_bio = NULL; pblk_write(kparams, pblkv[idx], pagev[idx]);
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);
} }
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);
} }

View File

@ -43,8 +43,8 @@ int verbose(uint level, const char* fmt, ...);
bool ask_user_bool(tristate_t auto_response, 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_read(int fd, u64 pblk, u32 count, u8* data);
void pblk_write(int fd, u32 pblk_size, u64 pblk, u32 count, const u8* data); void pblk_write(int fd, u64 pblk, u32 count, const u8* data);
void cbd_check_header(const struct cbd_header* header); void cbd_check_header(const struct cbd_header* header);

View File

@ -25,6 +25,13 @@
#define PAGE_SIZE (1 << PAGE_SHIFT) #define PAGE_SIZE (1 << PAGE_SHIFT)
#endif #endif
#ifndef PBLK_SHIFT
#define PBLK_SHIFT 12
#endif
#ifndef PBLK_SIZE
#define PBLK_SIZE (1 << PBLK_SHIFT)
#endif
#ifndef min #ifndef min
#define min(a, b) ((a) < (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b))
#endif #endif
@ -54,8 +61,7 @@ typedef uint64_t u64;
#include <stdlib.h> #include <stdlib.h>
#define CBD_DEFAULT_COMPRESSION_FACTOR 2.0 #define CBD_DEFAULT_COMPRESSION_FACTOR 1.5
#define CBD_DEFAULT_PHYSICAL_BLOCK_SHIFT 3
#define CBD_DEFAULT_LOGICAL_BLOCK_SHIFT 4 #define CBD_DEFAULT_LOGICAL_BLOCK_SHIFT 4
/* XXX: move to types.h */ /* XXX: move to types.h */
@ -68,8 +74,7 @@ typedef enum {
int cbd_format(const char* dev, int cbd_format(const char* dev,
uint16_t flags, uint16_t flags,
enum cbd_alg alg, uint level, enum cbd_alg alg, uint level,
uint8_t pshift, uint8_t lshift, uint8_t lshift,
uint8_t pbatshift,
uint64_t psize, uint64_t lsize, uint64_t psize, uint64_t lsize,
bool full_init); bool full_init);
int cbd_open(const char* dev, int cbd_open(const char* dev,

View File

@ -1,12 +1,13 @@
#ifndef _LINUX_DM_COMPRESS_H #ifndef _LINUX_DM_COMPRESS_H
#define _LINUX_DM_COMPRESS_H #define _LINUX_DM_COMPRESS_H
#define PBLK_SHIFT_MIN 0 #define PBLK_SHIFT 12
#define PBLK_SHIFT_MAX 3 #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_MIN 1
#define LBLK_SHIFT_MAX 10 #define LBLK_SHIFT_MAX 10
#define PBAT_SHIFT_MIN 0
#define PBAT_SHIFT_MAX 3
#define ZONE_NONE (u32)(~0) #define ZONE_NONE (u32)(~0)
#define PBLK_NONE (u64)(~0) #define PBLK_NONE (u64)(~0)
@ -35,11 +36,9 @@ enum cbd_alg {
struct cbd_params { struct cbd_params {
u16 flags; u16 flags;
u8 compression; /* alg and level */ u8 compression; /* alg and level */
u8 pblk_shift;
u8 lblk_shift; u8 lblk_shift;
u8 lba_elem_pblk_bytes; u8 lba_elem_pblk_bytes;
u8 pbat_shift; /* u8 pad[3] */
/* u8 pad */
u32 nr_zones; u32 nr_zones;
u32 lblk_per_zone; u32 lblk_per_zone;
u32 init_zones; 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 static inline u32
pblk_size_bits(const struct cbd_params* params) pblk_size_bits(const struct cbd_params* params)
{ {
return pblk_size(params) * BITS_PER_BYTE; return PBLK_SIZE * BITS_PER_BYTE;
} }
static inline u32 static inline u32
@ -252,13 +245,7 @@ lblk_per_pblk(const struct cbd_params* params)
static inline u32 static inline u32
lblk_size(const struct cbd_params* params) lblk_size(const struct cbd_params* params)
{ {
return pblk_size(params) * lblk_per_pblk(params); return PBLK_SIZE * lblk_per_pblk(params);
}
static inline u32
pbat_len(const struct cbd_params* params)
{
return (1 << params->pbat_shift);
} }
static inline u32 static inline u32
@ -283,20 +270,19 @@ lba_len(const struct cbd_params* params)
static inline u32 static inline u32
lbat_len(const struct cbd_params* params) 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 static inline u32
zone_metadata_len(const struct cbd_params* params) zone_metadata_len(const struct cbd_params* params)
{ {
return pbat_len(params) + return 1 + lbat_len(params);
lbat_len(params);
} }
static inline u32 static inline u32
zone_data_len(const struct cbd_params* params) 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 static inline u32
@ -321,16 +307,13 @@ pbat_off(const struct cbd_params* params, u32 idx)
static inline u64 static inline u64
lbat_off(const struct cbd_params* params, u32 idx) lbat_off(const struct cbd_params* params, u32 idx)
{ {
return zone_off(params, idx) + return zone_off(params, idx) + 1;
pbat_len(params);
} }
static inline u64 static inline u64
zone_data_off(const struct cbd_params* params, u32 idx) zone_data_off(const struct cbd_params* params, u32 idx)
{ {
return zone_off(params, idx) + return lbat_off(params, idx) + lbat_len(params);
pbat_len(params) +
lbat_len(params);
} }
static inline u32 static inline u32
@ -358,11 +341,9 @@ cbd_header_get(const u8* buf, struct cbd_header* header)
header->version_minor = get16_le(&p); header->version_minor = get16_le(&p);
header->params.flags = get16_le(&p); header->params.flags = get16_le(&p);
header->params.compression = get_byte(&p); header->params.compression = get_byte(&p);
header->params.pblk_shift = get_byte(&p);
header->params.lblk_shift = get_byte(&p); header->params.lblk_shift = get_byte(&p);
header->params.lba_elem_pblk_bytes = get_byte(&p); header->params.lba_elem_pblk_bytes = get_byte(&p);
header->params.pbat_shift = get_byte(&p); p += 3; /* pad */
p += 1; /* pad */
header->params.nr_zones = get32_le(&p); header->params.nr_zones = get32_le(&p);
header->params.lblk_per_zone = get32_le(&p); header->params.lblk_per_zone = get32_le(&p);
header->params.init_zones = 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->version_minor);
put16_le(&p, header->params.flags); put16_le(&p, header->params.flags);
put_byte(&p, header->params.compression); 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.lblk_shift);
put_byte(&p, header->params.lba_elem_pblk_bytes); 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 */ put_byte(&p, 0); /* pad */
put32_le(&p, header->params.nr_zones); put32_le(&p, header->params.nr_zones);
put32_le(&p, header->params.lblk_per_zone); 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 */ /* Core low-level I/O */
#define PBLK_IOV_MAX (PAGE_SIZE / SECTOR_SIZE) #define PBLK_IOV_MAX (PAGE_SIZE / SECTOR_SIZE)
int pblk_read_wait(struct compress_params* kparams, 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, 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, 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, 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, void pblk_writev(struct compress_params* kparams,
u64* pblkv, u32 count, struct page* page); u64* pblkv, struct page** pagev, u32 count);
struct pbat; struct pbat;
u32 pbat_zone(struct pbat* pbat); u32 pbat_zone(struct pbat* pbat);

View File

@ -24,25 +24,25 @@ struct check_state
static void static void
pbat_read(int fd, const struct cbd_params* params, u32 zone, u8* data) 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 static void
pbat_write(int fd, const struct cbd_params* params, u32 zone, const u8* data) 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 static void
lbat_read(int fd, const struct cbd_params* params, u32 zone, u8* data) 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 static void
lbat_write(int fd, const struct cbd_params* params, u32 zone, const u8* data) 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 static bool
@ -119,16 +119,16 @@ check_lblk_data(struct check_state* state,
u32 n; u32 n;
u64 pblk; u64 pblk;
data = calloc(pblk_size(params), lblk_per_pblk(params)); data = calloc(PBLK_SIZE, lblk_per_pblk(params));
buf = lba; buf = lba;
len = lba_len_get(params, buf); len = lba_len_get(params, buf);
if (len == 0 || len == CBD_UNCOMPRESSED) { if (len == 0 || len == CBD_UNCOMPRESSED) {
return true; 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) { for (n = 0; n < n_alloc; ++n) {
pblk = lba_pblk_get(params, buf, 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); ret = check_decompress(state, params, data, len);
free(data); free(data);
@ -179,7 +179,7 @@ check_lblk_alloc(struct check_state* state,
} }
n_alloc = (len == CBD_UNCOMPRESSED) ? n_alloc = (len == CBD_UNCOMPRESSED) ?
lblk_per_pblk(params) : lblk_per_pblk(params) :
DIV_ROUND_UP(len, pblk_size(params)); DIV_ROUND_UP(len, PBLK_SIZE);
for (n = 0; n < n_alloc; ++n) { for (n = 0; n < n_alloc; ++n) {
pblk = lba_pblk_get(params, buf, n); pblk = lba_pblk_get(params, buf, n);
if (pblk < CBD_HEADER_BLOCKS) { if (pblk < CBD_HEADER_BLOCKS) {
@ -239,7 +239,7 @@ check_lbat(struct check_state* state, const struct cbd_params* params)
u32 zone; u32 zone;
for (zone = 0; zone < params->init_zones; ++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 zone_empty = true;
bool changed = false; bool changed = false;
u32 n; u32 n;
@ -288,14 +288,14 @@ check_pbat(struct check_state* state, const struct cbd_params* params)
u32 zone; u32 zone;
u8* pbat; u8* pbat;
pbat = malloc(pblk_size(params) * pbat_len(params)); pbat = malloc(PBLK_SIZE);
for (zone = 0; zone < params->init_zones; ++zone) { for (zone = 0; zone < params->init_zones; ++zone) {
bool changed = false; bool changed = false;
pbat_read(state->fd, params, zone, pbat); 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, if (ask_user_bool(state->auto_response,
"zone %u has incorrect pbat. Fix?", zone)) { "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; changed = true;
} }
else { else {
@ -317,7 +317,7 @@ cbd_check(const char* dev,
{ {
struct check_state state; struct check_state state;
struct cbd_header header; struct cbd_header header;
uint8_t buf[SECTOR_SIZE]; uint8_t buf[PBLK_SIZE];
u32 n; u32 n;
memset(&state, 0, sizeof(state)); memset(&state, 0, sizeof(state));
@ -327,7 +327,7 @@ cbd_check(const char* dev,
} }
verbose(1, "Reading header\n"); 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); cbd_header_get(buf, &header);
verbose(1, "Checking header\n"); verbose(1, "Checking header\n");
cbd_check_header(&header); cbd_check_header(&header);
@ -346,7 +346,7 @@ cbd_check(const char* dev,
state.clean = true; state.clean = true;
state.pbatv = calloc(header.params.nr_zones, sizeof(u8*)); state.pbatv = calloc(header.params.nr_zones, sizeof(u8*));
for (n = 0; n < header.params.nr_zones; ++n) { 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) { if (full_check) {
state.compress_buf = malloc(lblk_size(&header.params)); 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); header.params.flags &= ~(CBD_FLAG_ERROR | CBD_FLAG_DIRTY);
cbd_header_put(buf, &header); cbd_header_put(buf, &header);
pblk_write(state.fd, SECTOR_SIZE, 0, 1, buf); pblk_write(state.fd, 0, 1, buf);
} }
close(state.fd); close(state.fd);

View File

@ -9,13 +9,11 @@ int
cbd_format(const char* dev, cbd_format(const char* dev,
uint16_t flags, uint16_t flags,
enum cbd_alg alg, uint level, enum cbd_alg alg, uint level,
uint8_t pshift, uint8_t lshift, uint8_t lshift,
uint8_t pbatshift,
uint64_t psize, uint64_t lsize, uint64_t psize, uint64_t lsize,
bool full_init) bool full_init)
{ {
int fd; int fd;
uint pblk_size;
uint lblk_size; uint lblk_size;
uint32_t est_zone_len; uint32_t est_zone_len;
struct cbd_header header; struct cbd_header header;
@ -35,14 +33,6 @@ cbd_format(const char* dev,
if (level < 1 || level > 9) { if (level < 1 || level > 9) {
error("Compression level %u out of bounds\n", level); 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) { if (!lshift) {
lshift = CBD_DEFAULT_LOGICAL_BLOCK_SHIFT; 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", error("Logical block shift %u is not in [%u,%u]\n",
(uint)lshift, (uint)LBLK_SHIFT_MIN, (uint)LBLK_SHIFT_MAX); (uint)lshift, (uint)LBLK_SHIFT_MIN, (uint)LBLK_SHIFT_MAX);
} }
lblk_size = pblk_size * (1 << lshift); 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);
}
if (!psize) { if (!psize) {
off_t pos; off_t pos;
pos = lseek(fd, 0, SEEK_END); pos = lseek(fd, 0, SEEK_END);
if (pos == (off_t)-1) { if (pos == (off_t)-1) {
error("Cannot seek device\n"); error("Cannot seek device\n");
} }
psize = pos / pblk_size * pblk_size; psize = pos / PBLK_SIZE * PBLK_SIZE;
} }
if (psize % pblk_size) { if (psize % PBLK_SIZE) {
error("Physical size %lu is not a multiple of %u bytes\n", (ulong)psize, pblk_size); error("Physical size %lu is not a multiple of %u bytes\n", (ulong)psize, PBLK_SIZE);
} }
if (!lsize) { if (!lsize) {
/* XXX: Why is the cast needed here? */ /* XXX: Why is the cast needed here? */
@ -75,9 +61,7 @@ cbd_format(const char* dev,
} }
printf("%s: parameters...\n", __func__); printf("%s: parameters...\n", __func__);
printf(" pshift=%u\n", (unsigned int)pshift);
printf(" lshift=%u\n", (unsigned int)lshift); printf(" lshift=%u\n", (unsigned int)lshift);
printf(" pbatshift=%u\n", (unsigned int)pbatshift);
printf(" alg=%d\n", (int)alg); printf(" alg=%d\n", (int)alg);
printf(" level=%u\n", level); printf(" level=%u\n", level);
printf(" psize=%lu\n", (unsigned long)psize); printf(" psize=%lu\n", (unsigned long)psize);
@ -90,22 +74,17 @@ cbd_format(const char* dev,
header.params.compression = 0; header.params.compression = 0;
cbd_compression_alg_put(&header.params, alg); cbd_compression_alg_put(&header.params, alg);
cbd_compression_level_put(&header.params, level); cbd_compression_level_put(&header.params, level);
header.params.pblk_shift = pshift;
header.params.lblk_shift = lshift; header.params.lblk_shift = lshift;
header.params.lba_elem_pblk_bytes = header.params.lba_elem_pblk_bytes =
((psize / pblk_size) <= 0xffff ? 2 : ((psize / PBLK_SIZE) <= 0xffff ? 2 :
((psize / pblk_size) <= 0xffffffff ? 4 : 6)); ((psize / PBLK_SIZE) <= 0xffffffff ? 4 : 6));
header.params.pbat_shift = pbatshift; if (lba_len(&header.params) > PBLK_SIZE) {
if (pbat_len(&header.params) * pblk_size > PAGE_SIZE) {
error("Physical block allocation table too large\n");
}
if (lba_len(&header.params) > pblk_size) {
error("lba element size too large\n"); error("lba element size too large\n");
} }
/* XXX: Initial estimate */ /* 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); 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); est_zone_len = zone_len(&header.params);
header.params.lblk_per_zone = DIV_ROUND_UP(lsize / lblk_size, header.params.nr_zones); header.params.lblk_per_zone = DIV_ROUND_UP(lsize / lblk_size, header.params.nr_zones);
while (zone_len(&header.params) > est_zone_len) { while (zone_len(&header.params) > est_zone_len) {
@ -114,16 +93,14 @@ cbd_format(const char* dev,
header.params.init_zones = 0; header.params.init_zones = 0;
printf("%s: header...\n", __func__); printf("%s: header...\n", __func__);
printf(" compression=0x%02x\n", (unsigned int)header.params.compression); 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(" 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(" 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(" nr_zones=%u\n", (unsigned int)header.params.nr_zones);
printf(" lblk_per_zone=%u\n", (unsigned int)header.params.lblk_per_zone); printf(" lblk_per_zone=%u\n", (unsigned int)header.params.lblk_per_zone);
memset(header_buf, 0, sizeof(header_buf)); memset(header_buf, 0, sizeof(header_buf));
cbd_header_put(header_buf, &header); 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) { if (full_init) {
uint32_t nr_pblk = zone_metadata_len(&header.params); uint32_t nr_pblk = zone_metadata_len(&header.params);
@ -134,24 +111,24 @@ cbd_format(const char* dev,
printf("Writing %lu zones ...\n", printf("Writing %lu zones ...\n",
(unsigned long)header.params.nr_zones); (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; next_write = time(NULL) + 5;
while (header.params.init_zones < header.params.nr_zones) { while (header.params.init_zones < header.params.nr_zones) {
pblk = zone_off(&header.params, header.params.init_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; ++header.params.init_zones;
now = time(NULL); now = time(NULL);
if (now >= next_write) { if (now >= next_write) {
printf("Initialized %u/%u zones\n", printf("Initialized %u/%u zones\n",
header.params.init_zones, header.params.nr_zones); header.params.init_zones, header.params.nr_zones);
cbd_header_put(header_buf, &header); 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; next_write = now + 5;
} }
} }
free(data_buf); free(data_buf);
cbd_header_put(header_buf, &header); cbd_header_put(header_buf, &header);
pblk_write(fd, pblk_size, 0, 1, header_buf); pblk_write(fd, 0, 1, header_buf);
} }
return 0; return 0;

View File

@ -8,7 +8,7 @@ static uint64_t
device_logical_sectors(const char* dev) device_logical_sectors(const char* dev)
{ {
int fd; int fd;
uint8_t buf[SECTOR_SIZE]; uint8_t buf[PBLK_SIZE];
struct cbd_header header; struct cbd_header header;
uint64_t lblk_total; 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; 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 int

View File

@ -6,7 +6,7 @@ int
cbd_stats(const char* dev, struct cbd_stats* stats) cbd_stats(const char* dev, struct cbd_stats* stats)
{ {
int fd; int fd;
uint8_t buf[SECTOR_SIZE]; uint8_t buf[PBLK_SIZE];
struct cbd_header header; struct cbd_header header;
fd = open(dev, O_RDONLY); fd = open(dev, O_RDONLY);

View File

@ -9,14 +9,14 @@ cbd_tune(const char* dev,
tristate_t zero_detect, uint level, bool repack) tristate_t zero_detect, uint level, bool repack)
{ {
int fd; int fd;
uint8_t header_buf[SECTOR_SIZE]; uint8_t header_buf[PBLK_SIZE];
struct cbd_header header; struct cbd_header header;
fd = open(dev, O_RDWR); fd = open(dev, O_RDWR);
if (fd < 0) { if (fd < 0) {
error("Cannot open device"); 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_header_get(header_buf, &header);
cbd_check_header(&header); cbd_check_header(&header);
@ -32,7 +32,7 @@ cbd_tune(const char* dev,
cbd_compression_level_put(&header.params, level); cbd_compression_level_put(&header.params, level);
} }
cbd_header_put(header_buf, &header); cbd_header_put(header_buf, &header);
pblk_write(fd, SECTOR_SIZE, 0, 1, header_buf); pblk_write(fd, 0, 1, header_buf);
if (repack) { if (repack) {
error("repack not supported yet\n"); error("repack not supported yet\n");

View File

@ -74,18 +74,18 @@ again:
} }
void 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; off_t pos;
size_t remain; size_t remain;
ssize_t ret; ssize_t ret;
pos = lseek(fd, pblk * pblk_size, SEEK_SET); pos = lseek(fd, pblk * PBLK_SIZE, SEEK_SET);
if (pos == (off_t)-1) { if (pos == (off_t)-1) {
error("Failed to seek\n"); error("Failed to seek\n");
} }
remain = count * pblk_size; remain = count * PBLK_SIZE;
while (remain) { while (remain) {
ret = read(fd, data, remain); ret = read(fd, data, remain);
if (ret <= 0) { if (ret <= 0) {
@ -97,18 +97,18 @@ pblk_read(int fd, u32 pblk_size, u64 pblk, u32 count, u8* data)
} }
void 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; off_t pos;
size_t remain; size_t remain;
ssize_t ret; ssize_t ret;
pos = lseek(fd, pblk * pblk_size, SEEK_SET); pos = lseek(fd, pblk * PBLK_SIZE, SEEK_SET);
if (pos == (off_t)-1) { if (pos == (off_t)-1) {
error("Failed to seek\n"); error("Failed to seek\n");
} }
remain = count * pblk_size; remain = count * PBLK_SIZE;
while (remain) { while (remain) {
ret = write(fd, data, remain); ret = write(fd, data, remain);
if (ret <= 0) { if (ret <= 0) {