]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
dm writecache: return the exact table values that were set
authorMikulas Patocka <mpatocka@redhat.com>
Thu, 4 Feb 2021 10:20:52 +0000 (05:20 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 28 Jul 2021 09:13:44 +0000 (11:13 +0200)
commit 054bee16163df023e2589db09fd27d81f7ad9e72 upstream.

LVM doesn't like it when the target returns different values from what
was set in the constructor. Fix dm-writecache so that the returned
table values are exactly the same as requested values.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Cc: stable@vger.kernel.org # v4.18+
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/md/dm-writecache.c

index a1d4166864d034d45261706334a927bbb79d50ea..51ba6caa7daef2d4d369ddb515ed9997243b9da5 100644 (file)
@@ -153,6 +153,7 @@ struct dm_writecache {
        bool overwrote_committed:1;
        bool memory_vmapped:1;
 
+       bool start_sector_set:1;
        bool high_wm_percent_set:1;
        bool low_wm_percent_set:1;
        bool max_writeback_jobs_set:1;
@@ -161,6 +162,10 @@ struct dm_writecache {
        bool writeback_fua_set:1;
        bool flush_on_suspend:1;
 
+       unsigned high_wm_percent_value;
+       unsigned low_wm_percent_value;
+       unsigned autocommit_time_value;
+
        unsigned writeback_all;
        struct workqueue_struct *writeback_wq;
        struct work_struct writeback_work;
@@ -2045,6 +2050,7 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
                        if (sscanf(string, "%llu%c", &start_sector, &dummy) != 1)
                                goto invalid_optional;
                        wc->start_sector = start_sector;
+                       wc->start_sector_set = true;
                        if (wc->start_sector != start_sector ||
                            wc->start_sector >= wc->memory_map_size >> SECTOR_SHIFT)
                                goto invalid_optional;
@@ -2054,6 +2060,7 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
                                goto invalid_optional;
                        if (high_wm_percent < 0 || high_wm_percent > 100)
                                goto invalid_optional;
+                       wc->high_wm_percent_value = high_wm_percent;
                        wc->high_wm_percent_set = true;
                } else if (!strcasecmp(string, "low_watermark") && opt_params >= 1) {
                        string = dm_shift_arg(&as), opt_params--;
@@ -2061,6 +2068,7 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
                                goto invalid_optional;
                        if (low_wm_percent < 0 || low_wm_percent > 100)
                                goto invalid_optional;
+                       wc->low_wm_percent_value = low_wm_percent;
                        wc->low_wm_percent_set = true;
                } else if (!strcasecmp(string, "writeback_jobs") && opt_params >= 1) {
                        string = dm_shift_arg(&as), opt_params--;
@@ -2080,6 +2088,7 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
                        if (autocommit_msecs > 3600000)
                                goto invalid_optional;
                        wc->autocommit_jiffies = msecs_to_jiffies(autocommit_msecs);
+                       wc->autocommit_time_value = autocommit_msecs;
                        wc->autocommit_time_set = true;
                } else if (!strcasecmp(string, "fua")) {
                        if (WC_MODE_PMEM(wc)) {
@@ -2275,7 +2284,6 @@ static void writecache_status(struct dm_target *ti, status_type_t type,
        struct dm_writecache *wc = ti->private;
        unsigned extra_args;
        unsigned sz = 0;
-       uint64_t x;
 
        switch (type) {
        case STATUSTYPE_INFO:
@@ -2287,7 +2295,7 @@ static void writecache_status(struct dm_target *ti, status_type_t type,
                DMEMIT("%c %s %s %u ", WC_MODE_PMEM(wc) ? 'p' : 's',
                                wc->dev->name, wc->ssd_dev->name, wc->block_size);
                extra_args = 0;
-               if (wc->start_sector)
+               if (wc->start_sector_set)
                        extra_args += 2;
                if (wc->high_wm_percent_set)
                        extra_args += 2;
@@ -2303,26 +2311,18 @@ static void writecache_status(struct dm_target *ti, status_type_t type,
                        extra_args++;
 
                DMEMIT("%u", extra_args);
-               if (wc->start_sector)
+               if (wc->start_sector_set)
                        DMEMIT(" start_sector %llu", (unsigned long long)wc->start_sector);
-               if (wc->high_wm_percent_set) {
-                       x = (uint64_t)wc->freelist_high_watermark * 100;
-                       x += wc->n_blocks / 2;
-                       do_div(x, (size_t)wc->n_blocks);
-                       DMEMIT(" high_watermark %u", 100 - (unsigned)x);
-               }
-               if (wc->low_wm_percent_set) {
-                       x = (uint64_t)wc->freelist_low_watermark * 100;
-                       x += wc->n_blocks / 2;
-                       do_div(x, (size_t)wc->n_blocks);
-                       DMEMIT(" low_watermark %u", 100 - (unsigned)x);
-               }
+               if (wc->high_wm_percent_set)
+                       DMEMIT(" high_watermark %u", wc->high_wm_percent_value);
+               if (wc->low_wm_percent_set)
+                       DMEMIT(" low_watermark %u", wc->low_wm_percent_value);
                if (wc->max_writeback_jobs_set)
                        DMEMIT(" writeback_jobs %u", wc->max_writeback_jobs);
                if (wc->autocommit_blocks_set)
                        DMEMIT(" autocommit_blocks %u", wc->autocommit_blocks);
                if (wc->autocommit_time_set)
-                       DMEMIT(" autocommit_time %u", jiffies_to_msecs(wc->autocommit_jiffies));
+                       DMEMIT(" autocommit_time %u", wc->autocommit_time_value);
                if (wc->writeback_fua_set)
                        DMEMIT(" %sfua", wc->writeback_fua ? "" : "no");
                break;