Add flags to header

Initial flag definition includes dirty flag.

Also remove unused pblk_read().

Also add pbat-len arg to format.
This commit is contained in:
Tom Marshall 2019-11-04 06:14:37 -08:00
parent 141888fa98
commit f37155f527
7 changed files with 98 additions and 22 deletions

View File

@ -85,6 +85,7 @@ usage(void)
" format [opts] <device> Create (format) a compressed device\n"
" -S --pysical-size Physical size [device size]\n"
" -L --logical-blksize Logical block size\n"
" -P --pbat-len Physical block allocation table length [1]\n"
" -c --compress-factor Compression factor [2.0]\n"
" -l --logical-shift Logical block shift [4]\n"
" -s --size Logical size\n"
@ -100,6 +101,7 @@ usage(void)
" create [opts] <device> <name> Alias for open\n"
" close [opts] <name> Close an opened compressed device\n"
" check [opts] <device> Check and repair a compressed device\n"
" -f --force Force check even if device seems clean\n"
" -n --assume-no Assume \"no\" no all questions\n"
" -y --assume-yes Assume \"yes\" to all questions\n"
" resize [opts] <device> Resize an existing compressed device\n"
@ -112,10 +114,11 @@ usage(void)
static int
do_format(int argc, char** argv)
{
static const char short_opts[] = "S:L:c:l:s:z:Z:";
static const char short_opts[] = "S:L:P:c:l:s:z:Z:";
static const struct option long_opts[] = {
{ "physical-size", required_argument, NULL, 'S' },
{ "logical-blksize", required_argument, NULL, 'L' },
{ "pbat-len", required_argument, NULL, 'P' },
{ "compress-factor", required_argument, NULL, 'c' },
{ "logical-shift", required_argument, NULL, 'l' },
{ "size", required_argument, NULL, 's' },
@ -126,6 +129,7 @@ do_format(int argc, char** argv)
char opt;
uint64_t optval;
uint64_t psize = 0;
uint16_t pbatlen = 1;
uint16_t lshift = 0;
uint64_t lsize = 0;
enum cbd_alg alg = CBD_ALG_LZ4;
@ -150,6 +154,12 @@ do_format(int argc, char** argv)
}
lshift = (optval >> PBLK_SHIFT);
break;
case 'P':
if (!parse_numeric_arg(optarg, &optval)) {
error("Failed to parse \"%s\"\n", optarg);
}
pbatlen = optval;
break;
case 'c':
error("Implement me!\n");
break;
@ -195,7 +205,7 @@ do_format(int argc, char** argv)
}
dev = argv[optind++];
cbd_format(dev, psize, lshift, lsize, alg, level);
cbd_format(dev, psize, pbatlen, lshift, lsize, alg, level);
return 0;
}
@ -253,25 +263,23 @@ do_stats(int argc, char** argv)
static int
do_check(int argc, char** argv)
{
static const char short_opts[] = "ny";
static const char short_opts[] = "fny";
static const struct option long_opts[] = {
{ "force", no_argument, NULL, 'f' },
{ "assume-no", no_argument, NULL, 'n' },
{ "assume-yes", no_argument, NULL, 'y' },
{ NULL, no_argument, NULL, 0 }
};
char opt;
bool force = false;
tristate_t auto_response = t_none;
const char* dev;
while ((opt = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
switch (opt) {
case 'y':
if (auto_response == t_false) {
fprintf(stderr, "Cannot specify both -y and -n\n");
usage();
}
auto_response = t_true;
case 'f':
force = true;
break;
case 'n':
if (auto_response == t_true) {
@ -280,6 +288,13 @@ do_check(int argc, char** argv)
}
auto_response = t_false;
break;
case 'y':
if (auto_response == t_false) {
fprintf(stderr, "Cannot specify both -y and -n\n");
usage();
}
auto_response = t_true;
break;
default:
usage();
}
@ -289,7 +304,7 @@ do_check(int argc, char** argv)
}
dev = argv[optind++];
cbd_check(dev, auto_response);
cbd_check(dev, force, auto_response);
return 0;
}

View File

@ -162,6 +162,36 @@ out:
return ret;
}
static int
compress_write_header(struct compress* c)
{
int ret = 0;
struct page* pblkpage;
u8* pblkbuf;
struct cbd_header header;
struct page* iopagev[1];
pblkpage = cbd_alloc_page();
if (!pblkpage) {
return -ENOMEM;
}
pblkbuf = page_address(pblkpage);
memset(&header, 0, sizeof(header));
memcpy(header.magic, CBD_MAGIC, sizeof(header.magic));
header.version_major = CBD_VERSION_MAJOR;
header.version_minor = CBD_VERSION_MINOR;
memcpy(&header.params, &c->params, sizeof(header.params));
cbd_header_put(pblkbuf, &header);
iopagev[0] = pblkpage;
ret = pblk_write_wait(c->params.priv, 0, 1, iopagev);
if (ret) {
printk(KERN_ERR "%s: failed to write header\n", __func__);
}
cbd_free_page(pblkpage);
return ret;
}
static struct lbd*
compress_lbdcache_swap(struct compress* c, u64 lblk, struct lbd* oldlbd)
{
@ -365,6 +395,18 @@ compress_ctr(struct dm_target *ti, unsigned int argc, char **argv)
if (ret) {
goto err;
}
if (c->params.flags & CBD_FLAG_DIRTY) {
printk(KERN_INFO "Warning: device was not properly closed\n");
}
if (dm_table_get_mode(ti->table) & FMODE_WRITE) {
u16 save_flags = c->params.flags;
c->params.flags |= CBD_FLAG_DIRTY;
ret = compress_write_header(c);
c->params.flags = save_flags;
if (ret) {
goto err;
}
}
/* XXX: validate minumum pblk using zone_off(max_zone+1) */
if (c->params.nr_pblk > dev_nr_pblks) {
@ -413,11 +455,19 @@ err:
static void
compress_dtr(struct dm_target *ti)
{
int ret;
struct compress *c;
printk(KERN_INFO "%s: enter\n", __func__);
c = ti->private;
if (dm_table_get_mode(ti->table) & FMODE_WRITE) {
ret = compress_write_header(c);
if (ret) {
printk(KERN_INFO "Warning: failed to write header\n");
}
}
lbdcache_dtr(c->lc);
kfree(c->lc);
if (c->io_workq) {

View File

@ -144,23 +144,19 @@ pblk_read_wait(struct block_device* bdev,
}
int
pblk_read(struct block_device* bdev,
u64 pblk, u32 count, struct page** pagev,
pblk_endio_t endio, void* endio_priv)
pblk_write_wait(struct block_device* bdev,
u64 pblk, u32 count, struct page** pagev)
{
int ret;
struct bio* bio;
bio = pblk_io_prepare(bdev, REQ_OP_READ, pblk, count, pagev);
bio = pblk_io_prepare(bdev, REQ_OP_WRITE, pblk, count, pagev);
if (!bio) {
printk(KERN_ERR "%s: out of memory\n", __func__);
return -ENOMEM;
}
bio->bi_end_io = endio;
bio->bi_private = endio_priv;
ret = submit_bio(bio);
if (ret != 0) {
ret = submit_bio_wait(bio);
if (ret) {
printk(KERN_ERR "%s: submit_bio_wait failed: %d\n", __func__, ret);
}
bio_put(bio);

View File

@ -4,6 +4,7 @@
/* Kernel compatibility */
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <asm/byteorder.h>
#ifndef BITS_PER_BYTE
@ -60,6 +61,7 @@ int cbd_close(const char* name);
int cbd_stats(const char* name);
int cbd_check(const char* dev,
bool force,
tristate_t auto_response);
int cbd_resize(const char* dev,
uint64_t lsize);

View File

@ -28,6 +28,8 @@ static const u8 CBD_MAGIC[] = { 'C', 'B', 'D', '\0' };
static const u16 CBD_VERSION_MAJOR = 1;
static const u16 CBD_VERSION_MINOR = 1;
#define CBD_FLAG_DIRTY 0x01
enum cbd_alg {
CBD_ALG_NONE,
CBD_ALG_LZ4,
@ -37,6 +39,7 @@ enum cbd_alg {
};
struct cbd_params {
u16 flags;
u8 algorithm; /* enum cbd_alg */
u8 compression; /* 0..9 */
u16 pbat_len;
@ -295,6 +298,7 @@ cbd_header_get(const u8* buf, struct cbd_header* header)
get_mem(&buf, header->magic, sizeof(header->magic));
header->version_major = get16_le(&buf);
header->version_minor = get16_le(&buf);
header->params.flags = get16_le(&buf);
header->params.algorithm = get_byte(&buf);
header->params.compression = get_byte(&buf);
header->params.pbat_len = get16_le(&buf);
@ -310,6 +314,7 @@ cbd_header_put(u8* buf, const struct cbd_header* header)
put_mem(&buf, header->magic, sizeof(header->magic));
put16_le(&buf, header->version_major);
put16_le(&buf, header->version_minor);
put16_le(&buf, header->params.flags);
put_byte(&buf, header->params.algorithm);
put_byte(&buf, header->params.compression);
put16_le(&buf, header->params.pbat_len);
@ -471,9 +476,8 @@ void cbd_free_pagev(struct page** pagev, size_t len);
/* Core low-level I/O */
int pblk_read_wait(struct block_device* bdev,
u64 pblk, u32 count, struct page** pagev);
int pblk_read(struct block_device* bdev,
u64 pblk, u32 count, struct page** pagev,
pblk_endio_t endio, void* endio_priv);
int pblk_write_wait(struct block_device* bdev,
u64 pblk, u32 count, struct page** pagev);
void pblk_write(struct block_device* bdev,
u64 pblk, u32 count, struct page** pagev);

View File

@ -184,6 +184,7 @@ check_zone_metadata(const struct cbd_params* params,
int
cbd_check(const char* dev,
bool force,
tristate_t auto_response)
{
int devfd;
@ -200,6 +201,11 @@ cbd_check(const char* dev,
pblk_read(devfd, 0, 1, pblkbuf);
cbd_header_get(pblkbuf, &header);
check_header(&header);
if (!force && !(header.params.flags & CBD_FLAG_DIRTY)) {
printf("%s: clean\n", dev);
close(devfd);
return 0;
}
zmvec = calloc(header.params.nr_zones, sizeof(struct zone_metadata));
for (zone = 0; zone < header.params.nr_zones; ++zone) {
@ -223,5 +229,7 @@ cbd_check(const char* dev,
}
free(zmvec);
close(devfd);
return 0;
}

View File

@ -88,6 +88,7 @@ cbd_format(const char* dev,
memcpy(header.magic, CBD_MAGIC, sizeof(header.magic));
header.version_major = CBD_VERSION_MAJOR;
header.version_minor = CBD_VERSION_MINOR;
header.params.flags = 0;
header.params.algorithm = alg;
header.params.compression = level;
header.params.pbat_len = pbatlen;