dm thin: commit before gathering status
authorAlasdair G Kergon <agk@redhat.com>
Fri, 27 Jul 2012 14:08:16 +0000 (15:08 +0100)
committerAlasdair G Kergon <agk@redhat.com>
Fri, 27 Jul 2012 14:08:16 +0000 (15:08 +0100)
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>
15 files changed:
drivers/md/dm-crypt.c
drivers/md/dm-delay.c
drivers/md/dm-flakey.c
drivers/md/dm-ioctl.c
drivers/md/dm-linear.c
drivers/md/dm-mpath.c
drivers/md/dm-raid.c
drivers/md/dm-raid1.c
drivers/md/dm-snap.c
drivers/md/dm-stripe.c
drivers/md/dm-thin.c
drivers/md/dm-verity.c
drivers/md/dm.h
include/linux/device-mapper.h
include/linux/dm-ioctl.h

index 00a25ab..664743d 100644 (file)
@@ -1733,7 +1733,7 @@ static int crypt_map(struct dm_target *ti, struct bio *bio,
 }
 
 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;
index 2dc22dd..f53846f 100644 (file)
@@ -295,7 +295,7 @@ static int delay_map(struct dm_target *ti, struct bio *bio,
 }
 
 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;
index ac49c01..cc15543 100644 (file)
@@ -333,7 +333,7 @@ static int flakey_end_io(struct dm_target *ti, struct bio *bio,
 }
 
 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;
index a1a3e6d..afd9598 100644 (file)
@@ -1054,6 +1054,7 @@ static void retrieve_status(struct dm_table *table,
        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 @@ static void retrieve_status(struct dm_table *table,
 
                /* 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;
                        }
index 3639eea..1bf19a9 100644 (file)
@@ -96,7 +96,7 @@ static int linear_map(struct dm_target *ti, struct bio *bio,
 }
 
 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;
 
index 8a3b2d5..d8abb90 100644 (file)
@@ -1378,7 +1378,7 @@ static void multipath_resume(struct dm_target *ti)
  *      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;
index f4275a8..f2f29c5 100644 (file)
@@ -1081,7 +1081,7 @@ static int raid_map(struct dm_target *ti, struct bio *bio, union map_info *map_c
 }
 
 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 */
index 596a3a1..bc5ddba 100644 (file)
@@ -1367,7 +1367,7 @@ static char device_status_char(struct mirror *m)
 
 
 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;
index 6c0f3e3..a143921 100644 (file)
@@ -1849,7 +1849,7 @@ static void snapshot_merge_resume(struct dm_target *ti)
 }
 
 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 @@ static void origin_resume(struct dm_target *ti)
        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;
 
index 9e8f4cc..a087bf2 100644 (file)
@@ -311,8 +311,8 @@ static int stripe_map(struct dm_target *ti, struct bio *bio,
  *
  */
 
-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];
index 087e9b3..af1fc3b 100644 (file)
@@ -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 @@ static void emit_flags(struct pool_features *pf, char *result,
  *    <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 @@ static int pool_status(struct dm_target *ti, status_type_t type,
                        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 @@ static void thin_postsuspend(struct dm_target *ti)
  * <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;
index fa365d3..254d192 100644 (file)
@@ -515,7 +515,7 @@ static int verity_map(struct dm_target *ti, struct bio *bio,
  * 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;
index b7dacd5..52eef49 100644 (file)
 #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
index eb75363..38d27a1 100644 (file)
@@ -72,7 +72,7 @@ typedef int (*dm_preresume_fn) (struct dm_target *ti);
 typedef void (*dm_resume_fn) (struct dm_target *ti);
 
 typedef int (*dm_status_fn) (struct dm_target *ti, status_type_t status_type,
-                            char *result, unsigned int maxlen);
+                            unsigned status_flags, char *result, unsigned maxlen);
 
 typedef int (*dm_message_fn) (struct dm_target *ti, unsigned argc, char **argv);
 
index 3ece4ee..91e3a36 100644 (file)
@@ -267,9 +267,9 @@ enum {
 #define DM_DEV_SET_GEOMETRY    _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
 
 #define DM_VERSION_MAJOR       4
-#define DM_VERSION_MINOR       22
-#define DM_VERSION_PATCHLEVEL  1
-#define DM_VERSION_EXTRA       "-ioctl (2012-06-01)"
+#define DM_VERSION_MINOR       23
+#define DM_VERSION_PATCHLEVEL  0
+#define DM_VERSION_EXTRA       "-ioctl (2012-07-25)"
 
 /* Status bits */
 #define DM_READONLY_FLAG       (1 << 0) /* In/Out */
@@ -307,6 +307,8 @@ enum {
 
 /*
  * Set this to suspend without flushing queued ios.
+ * Also disables flushing uncommitted changes in the thin target before
+ * generating statistics for DM_TABLE_STATUS and DM_DEV_WAIT.
  */
 #define DM_NOFLUSH_FLAG                (1 << 11) /* In */