From c6fe92715ccaa6dd4ae8e3064825ee973413feb1 Mon Sep 17 00:00:00 2001 From: Tom Marshall Date: Thu, 14 Nov 2019 18:51:46 +0100 Subject: [PATCH] Implement mount options cache_pages and sync Also fixup kernel arg parsing. --- cbd/cbd.c | 41 ++++++++++++++++++++++++++++++++----- dm-compress/compress.c | 15 +++++++++----- dm-compress/lbd.c | 22 ++++++++++++++------ include/libcbd.h | 3 ++- include/linux/dm-compress.h | 2 +- libcbd/open.c | 16 +++++++++++++-- 6 files changed, 79 insertions(+), 20 deletions(-) diff --git a/cbd/cbd.c b/cbd/cbd.c index 40c6ed3..0a508f3 100644 --- a/cbd/cbd.c +++ b/cbd/cbd.c @@ -150,6 +150,8 @@ usage(void) " archive: 4k pblk, 256k lblk, zlib level 9\n" "\n" " open [opts] Open an existing compressed device\n" + " -c --cache-pages Set cache pages\n" + " -s --sync Open in synchronous mode\n" " create [opts] Alias for open\n" " close [opts] Close an opened compressed device\n" " check [opts] 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; } diff --git a/dm-compress/compress.c b/dm-compress/compress.c index 5d31715..600522e 100644 --- a/dm-compress/compress.c +++ b/dm-compress/compress.c @@ -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; diff --git a/dm-compress/lbd.c b/dm-compress/lbd.c index 422da99..98252a2 100644 --- a/dm-compress/lbd.c +++ b/dm-compress/lbd.c @@ -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); diff --git a/include/libcbd.h b/include/libcbd.h index 83f7f1c..ea4ed8d 100644 --- a/include/libcbd.h +++ b/include/libcbd.h @@ -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); diff --git a/include/linux/dm-compress.h b/include/linux/dm-compress.h index b1547d5..4def15e 100644 --- a/include/linux/dm-compress.h +++ b/include/linux/dm-compress.h @@ -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); diff --git a/libcbd/open.c b/libcbd/open.c index 90611b6..2fd7da8 100644 --- a/libcbd/open.c +++ b/libcbd/open.c @@ -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"); }