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