Implement mount options cache_pages and sync

Also fixup kernel arg parsing.
This commit is contained in:
Tom Marshall 2019-11-14 18:51:46 +01:00
parent be3d28a255
commit c6fe92715c
6 changed files with 79 additions and 20 deletions

View File

@ -150,6 +150,8 @@ usage(void)
" archive: 4k pblk, 256k lblk, zlib level 9\n"
"\n"
" open [opts] <device> <name> Open an existing compressed device\n"
" -c --cache-pages Set cache pages\n"
" -s --sync Open in synchronous mode\n"
" 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"
@ -295,19 +297,48 @@ do_format(int argc, char** argv)
static int
do_open(int argc, char** argv)
{
static const char short_opts[] = "c:s";
static const struct option long_opts[] = {
{ "cache-pages", required_argument, NULL, 'c' },
{ "sync", no_argument, NULL, 's' },
{ NULL, no_argument, NULL, 0 }
};
char opt;
uint64_t optval;
uint64_t cache_pages = 0;
bool sync = false;
char dev[PATH_MAX];
const char* name;
if (argc != 3) {
while ((opt = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
switch (opt) {
case 'c':
if (!parse_numeric_arg(optarg, &optval)) {
error("Failed to parse \"%s\"\n", optarg);
}
if (optval < 1) {
error("Size \"%s\" is not a valid cache size\n", optarg);
}
cache_pages = optval;
break;
case 's':
sync = true;
break;
default:
usage();
}
}
if (argc - optind != 2) {
usage();
}
strcpy(dev, argv[1]);
strcpy(dev, argv[optind]);
if (dev[0] != '/') {
sprintf(dev, "/dev/mapper/%s", argv[1]);
sprintf(dev, "/dev/mapper/%s", argv[optind]);
}
name = argv[2];
++optind;
name = argv[optind++];
cbd_open(dev, name);
cbd_open(dev, name, cache_pages, sync);
return 0;
}

View File

@ -499,6 +499,7 @@ compress_ctr(struct dm_target *ti, unsigned int argc, char **argv)
int ret;
unsigned int argn;
u32 cache_pages = 0;
bool sync = false;
struct compress *c = NULL;
u64 target_nr_pblks;
@ -513,15 +514,16 @@ compress_ctr(struct dm_target *ti, unsigned int argc, char **argv)
argn = 1;
while (argn < argc) {
const char* arg = argv[argn++];
const char* val = NULL;
const char* eq = strchr(arg, '=');
char* arg = argv[argn++];
char* val = NULL;
char* eq = strchr(arg, '=');
int err;
if (eq) {
*eq = '\0';
val = eq + 1;
}
/* XXX: Parse suffixes */
if (!memcmp(arg, "cache_pages", 7)) {
if (!strcmp(arg, "cache_pages")) {
err = kstrtouint(eq + 1, 0, &cache_pages);
if (err) {
ti->error = "Failed to parse cache_pages";
@ -529,6 +531,9 @@ compress_ctr(struct dm_target *ti, unsigned int argc, char **argv)
}
continue;
}
if (!strcmp(arg, "sync")) {
sync = true;
}
ti->error = "Unrecognized argument";
return -EINVAL;
}
@ -606,7 +611,7 @@ compress_ctr(struct dm_target *ti, unsigned int argc, char **argv)
ret = -ENOMEM;
goto err;
}
if (!lbdcache_ctr(c->lc, &c->kparams, &c->kstats, cache_pages)) {
if (!lbdcache_ctr(c->lc, &c->kparams, &c->kstats, cache_pages, sync)) {
ti->error = "Failed to init logical block cache";
ret = -ENOMEM;
goto err;

View File

@ -533,6 +533,7 @@ lbd_data_write(struct lbd* lbd, u32 off, u32 len, const u8* buf)
struct lbdcache
{
struct cbd_params* params;
bool sync;
void* percpu;
struct lbatviewcache* lvc;
struct mutex cache_lock;
@ -628,7 +629,7 @@ lbdcache_free_compress_state(void* percpu, const struct cbd_params* params, int
bool
lbdcache_ctr(struct lbdcache* lc,
struct compress_params* kparams, struct compress_stats* kstats,
u32 cache_pages)
bool sync, u32 cache_pages)
{
int cpu;
struct lbd* cache;
@ -637,6 +638,7 @@ lbdcache_ctr(struct lbdcache* lc,
memset(lc, 0, sizeof(struct lbdcache));
lc->params = &kparams->params;
lc->sync = sync;
lc->percpu = alloc_percpu(void*);
for (cpu = 0; cpu < num_online_cpus(); ++cpu) {
if (!lbdcache_alloc_compress_state(lc->percpu, lc->params, cpu)) {
@ -849,11 +851,19 @@ lbdcache_put(struct lbdcache* lc, struct lbd* lbd)
mutex_lock(&lc->flush_lock);
mutex_lock(&lbd->reflock);
if (--lbd->ref == 0) {
lbd->flush_jiffies = jiffies + COMPRESS_FLUSH_DELAY;
lbd->ref = 1;
list_add_tail(&lbd->flush_list, &lc->flush_head);
if (!delayed_work_pending(&lc->flush_dwork)) {
schedule_delayed_work(&lc->flush_dwork, COMPRESS_FLUSH_DELAY);
if (lc->sync) {
ret = lbd_flush(lbd);
if (ret) {
printk(KERN_ERR "%s: lbd_flush failed\n", __func__);
}
}
else {
lbd->flush_jiffies = jiffies + COMPRESS_FLUSH_DELAY;
lbd->ref = 1;
list_add_tail(&lbd->flush_list, &lc->flush_head);
if (!delayed_work_pending(&lc->flush_dwork)) {
schedule_delayed_work(&lc->flush_dwork, COMPRESS_FLUSH_DELAY);
}
}
}
mutex_unlock(&lbd->reflock);

View File

@ -71,7 +71,8 @@ int cbd_format(const char* dev,
uint8_t pbatshift,
uint64_t psize, uint64_t lsize);
int cbd_open(const char* dev,
const char* name);
const char* name,
uint64_t cache_pages, bool sync);
int cbd_close(const char* name);
int cbd_stats(const char* dev, struct cbd_stats* stats);

View File

@ -648,7 +648,7 @@ struct lbdcache;
size_t lbdcache_size(void);
bool lbdcache_ctr(struct lbdcache* lc,
struct compress_params* kparams, struct compress_stats* kstats,
u32 cache_pages);
bool sync, u32 cache_pages);
void lbdcache_dtr(struct lbdcache* lc);
struct lbd*
lbdcache_get(struct lbdcache* lc, u64 lblk);

View File

@ -31,11 +31,14 @@ device_logical_size(const char* dev)
int
cbd_open(const char* dev,
const char* name)
const char* name,
uint64_t cache_pages, bool sync)
{
int ret;
struct stat st;
uint64_t lsize;
char optbuf[80];
char params[256];
struct dm_task* dmt;
uint32_t cookie = 0;
@ -48,6 +51,15 @@ cbd_open(const char* dev,
}
lsize = device_logical_size(dev);
strcpy(params, dev);
if (cache_pages) {
sprintf(optbuf, " cache_pages=%lu", (unsigned long)cache_pages);
strcat(params, optbuf);
}
if (sync) {
strcat(params, " sync");
}
dmt = dm_task_create(DM_DEVICE_CREATE);
if (!dmt) {
error("dm_task_create failed\n");
@ -62,7 +74,7 @@ cbd_open(const char* dev,
0,
lsize / SECTOR_SIZE,
"compress",
dev);
params);
if (ret == 0) {
error("dm_task_add_target failed\n");
}