dm thin: commit before gathering status
Commit outstanding metadata before returning the status for a dm thin
pool so that the numbers reported are as up-to-date as possible.
The commit is not performed if the device is suspended or if
the DM_NOFLUSH_FLAG is supplied by userspace and passed to the target
through a new 'status_flags' parameter in the target's dm_status_fn.
The userspace dmsetup tool will support the --noflush flag with the
'dmsetup status' and 'dmsetup wait' commands from version 1.02.76
onwards.
Tested-by: Mike Snitzer <snitzer@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 00a25ab..664743d 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -1733,7 +1733,7 @@
}
static int crypt_status(struct dm_target *ti, status_type_t type,
- char *result, unsigned int maxlen)
+ unsigned status_flags, char *result, unsigned maxlen)
{
struct crypt_config *cc = ti->private;
unsigned int sz = 0;
diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c
index 2dc22dd..f53846f 100644
--- a/drivers/md/dm-delay.c
+++ b/drivers/md/dm-delay.c
@@ -295,7 +295,7 @@
}
static int delay_status(struct dm_target *ti, status_type_t type,
- char *result, unsigned maxlen)
+ unsigned status_flags, char *result, unsigned maxlen)
{
struct delay_c *dc = ti->private;
int sz = 0;
diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c
index ac49c01..cc15543 100644
--- a/drivers/md/dm-flakey.c
+++ b/drivers/md/dm-flakey.c
@@ -333,7 +333,7 @@
}
static int flakey_status(struct dm_target *ti, status_type_t type,
- char *result, unsigned int maxlen)
+ unsigned status_flags, char *result, unsigned maxlen)
{
unsigned sz = 0;
struct flakey_c *fc = ti->private;
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index a1a3e6d..afd9598 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1054,6 +1054,7 @@
char *outbuf, *outptr;
status_type_t type;
size_t remaining, len, used = 0;
+ unsigned status_flags = 0;
outptr = outbuf = get_result_buffer(param, param_size, &len);
@@ -1090,7 +1091,9 @@
/* Get the status/table string from the target driver */
if (ti->type->status) {
- if (ti->type->status(ti, type, outptr, remaining)) {
+ if (param->flags & DM_NOFLUSH_FLAG)
+ status_flags |= DM_STATUS_NOFLUSH_FLAG;
+ if (ti->type->status(ti, type, status_flags, outptr, remaining)) {
param->flags |= DM_BUFFER_FULL_FLAG;
break;
}
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index 3639eea..1bf19a9 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -96,7 +96,7 @@
}
static int linear_status(struct dm_target *ti, status_type_t type,
- char *result, unsigned int maxlen)
+ unsigned status_flags, char *result, unsigned maxlen)
{
struct linear_c *lc = (struct linear_c *) ti->private;
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 8a3b2d5..d8abb90 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -1378,7 +1378,7 @@
* num_paths num_selector_args [path_dev [selector_args]* ]+ ]+
*/
static int multipath_status(struct dm_target *ti, status_type_t type,
- char *result, unsigned int maxlen)
+ unsigned status_flags, char *result, unsigned maxlen)
{
int sz = 0;
unsigned long flags;
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index f4275a8..f2f29c5 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -1081,7 +1081,7 @@
}
static int raid_status(struct dm_target *ti, status_type_t type,
- char *result, unsigned maxlen)
+ unsigned status_flags, char *result, unsigned maxlen)
{
struct raid_set *rs = ti->private;
unsigned raid_param_cnt = 1; /* at least 1 for chunksize */
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 596a3a1..bc5ddba8 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -1367,7 +1367,7 @@
static int mirror_status(struct dm_target *ti, status_type_t type,
- char *result, unsigned int maxlen)
+ unsigned status_flags, char *result, unsigned maxlen)
{
unsigned int m, sz = 0;
struct mirror_set *ms = (struct mirror_set *) ti->private;
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 6c0f3e3..a143921 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -1849,7 +1849,7 @@
}
static int snapshot_status(struct dm_target *ti, status_type_t type,
- char *result, unsigned int maxlen)
+ unsigned status_flags, char *result, unsigned maxlen)
{
unsigned sz = 0;
struct dm_snapshot *snap = ti->private;
@@ -2151,8 +2151,8 @@
ti->max_io_len = get_origin_minimum_chunksize(dev->bdev);
}
-static int origin_status(struct dm_target *ti, status_type_t type, char *result,
- unsigned int maxlen)
+static int origin_status(struct dm_target *ti, status_type_t type,
+ unsigned status_flags, char *result, unsigned maxlen)
{
struct dm_dev *dev = ti->private;
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index 9e8f4cc..a087bf2 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -311,8 +311,8 @@
*
*/
-static int stripe_status(struct dm_target *ti,
- status_type_t type, char *result, unsigned int maxlen)
+static int stripe_status(struct dm_target *ti, status_type_t type,
+ unsigned status_flags, char *result, unsigned maxlen)
{
struct stripe_c *sc = (struct stripe_c *) ti->private;
char buffer[sc->stripes + 1];
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index 087e9b3..af1fc3b 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -5,6 +5,7 @@
*/
#include "dm-thin-metadata.h"
+#include "dm.h"
#include <linux/device-mapper.h>
#include <linux/dm-io.h>
@@ -2619,7 +2620,7 @@
* <used data sectors>/<total data sectors> <held metadata root>
*/
static int pool_status(struct dm_target *ti, status_type_t type,
- char *result, unsigned maxlen)
+ unsigned status_flags, char *result, unsigned maxlen)
{
int r;
unsigned sz = 0;
@@ -2641,6 +2642,10 @@
break;
}
+ /* Commit to ensure statistics aren't out-of-date */
+ if (!(status_flags & DM_STATUS_NOFLUSH_FLAG) && !dm_suspended(ti))
+ (void) commit_or_fallback(pool);
+
r = dm_pool_get_metadata_transaction_id(pool->pmd,
&transaction_id);
if (r)
@@ -2968,7 +2973,7 @@
* <nr mapped sectors> <highest mapped sector>
*/
static int thin_status(struct dm_target *ti, status_type_t type,
- char *result, unsigned maxlen)
+ unsigned status_flags, char *result, unsigned maxlen)
{
int r;
ssize_t sz = 0;
diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c
index fa365d3..254d192 100644
--- a/drivers/md/dm-verity.c
+++ b/drivers/md/dm-verity.c
@@ -515,7 +515,7 @@
* Status: V (valid) or C (corruption found)
*/
static int verity_status(struct dm_target *ti, status_type_t type,
- char *result, unsigned maxlen)
+ unsigned status_flags, char *result, unsigned maxlen)
{
struct dm_verity *v = ti->private;
unsigned sz = 0;
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index b7dacd5..52eef49 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -23,6 +23,11 @@
#define DM_SUSPEND_NOFLUSH_FLAG (1 << 1)
/*
+ * Status feature flags
+ */
+#define DM_STATUS_NOFLUSH_FLAG (1 << 0)
+
+/*
* Type of table and mapped_device's mempool
*/
#define DM_TYPE_NONE 0