summaryrefslogtreecommitdiff
path: root/libdm/libdm-targets.c
diff options
context:
space:
mode:
authorAlasdair G Kergon <agk@redhat.com>2015-09-28 20:28:31 +0100
committerAlasdair G Kergon <agk@redhat.com>2015-09-28 20:28:31 +0100
commit0173c260d8270465f1895044b34609008962cc00 (patch)
tree8e6fc5364fb569ed5b7a7c3eea671683c93a8a57 /libdm/libdm-targets.c
parent9d815e5f5a17963a09b103177770e9af80c90e0f (diff)
downloadlvm2-0173c260d8270465f1895044b34609008962cc00.tar.gz
libdm: Move status fns from deptree to targets.
libdm-deptree is only for functions working with dm tree nodes.
Diffstat (limited to 'libdm/libdm-targets.c')
-rw-r--r--libdm/libdm-targets.c357
1 files changed, 357 insertions, 0 deletions
diff --git a/libdm/libdm-targets.c b/libdm/libdm-targets.c
new file mode 100644
index 000000000..f22ad9c3e
--- /dev/null
+++ b/libdm/libdm-targets.c
@@ -0,0 +1,357 @@
+/*
+ * Copyright (C) 2005-2015 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "dmlib.h"
+#include "libdm-common.h"
+
+int dm_get_status_snapshot(struct dm_pool *mem, const char *params,
+ struct dm_status_snapshot **status)
+{
+ struct dm_status_snapshot *s;
+ int r;
+
+ if (!params) {
+ log_error("Failed to parse invalid snapshot params.");
+ return 0;
+ }
+
+ if (!(s = dm_pool_zalloc(mem, sizeof(*s)))) {
+ log_error("Failed to allocate snapshot status structure.");
+ return 0;
+ }
+
+ r = sscanf(params, FMTu64 "/" FMTu64 " " FMTu64,
+ &s->used_sectors, &s->total_sectors,
+ &s->metadata_sectors);
+
+ if (r == 3 || r == 2)
+ s->has_metadata_sectors = (r == 3);
+ else if (!strcmp(params, "Invalid"))
+ s->invalid = 1;
+ else if (!strcmp(params, "Merge failed"))
+ s->merge_failed = 1;
+ else if (!strcmp(params, "Overflow"))
+ s->overflow = 1;
+ else {
+ dm_pool_free(mem, s);
+ log_error("Failed to parse snapshot params: %s.", params);
+ return 0;
+ }
+
+ *status = s;
+
+ return 1;
+}
+
+/*
+ * Various RAID status versions include:
+ * Versions < 1.5.0 (4 fields):
+ * <raid_type> <#devs> <health_str> <sync_ratio>
+ * Versions 1.5.0+ (6 fields):
+ * <raid_type> <#devs> <health_str> <sync_ratio> <sync_action> <mismatch_cnt>
+ */
+int dm_get_status_raid(struct dm_pool *mem, const char *params,
+ struct dm_status_raid **status)
+{
+ int i;
+ const char *pp, *p;
+ struct dm_status_raid *s;
+
+ if (!params || !(p = strchr(params, ' '))) {
+ log_error("Failed to parse invalid raid params.");
+ return 0;
+ }
+ p++;
+
+ /* second field holds the device count */
+ if (sscanf(p, "%d", &i) != 1)
+ return_0;
+
+ if (!(s = dm_pool_zalloc(mem, sizeof(struct dm_status_raid))))
+ return_0;
+
+ if (!(s->raid_type = dm_pool_zalloc(mem, p - params)))
+ goto_bad; /* memory is freed went pool is destroyed */
+
+ if (!(s->dev_health = dm_pool_zalloc(mem, i + 1)))
+ goto_bad;
+
+ if (sscanf(params, "%s %u %s %" PRIu64 "/%" PRIu64,
+ s->raid_type,
+ &s->dev_count,
+ s->dev_health,
+ &s->insync_regions,
+ &s->total_regions) != 5) {
+ log_error("Failed to parse raid params: %s", params);
+ goto bad;
+ }
+
+ *status = s;
+
+ /*
+ * All pre-1.5.0 version parameters are read. Now we check
+ * for additional 1.5.0+ parameters.
+ *
+ * Note that 'sync_action' will be NULL (and mismatch_count
+ * will be 0) if the kernel returns a pre-1.5.0 status.
+ */
+ for (p = params, i = 0; i < 4; i++, p++)
+ if (!(p = strchr(p, ' ')))
+ return 1; /* return pre-1.5.0 status */
+
+ pp = p;
+ if (!(p = strchr(p, ' '))) {
+ log_error(INTERNAL_ERROR "Bad RAID status received.");
+ goto bad;
+ }
+ p++;
+
+ if (!(s->sync_action = dm_pool_zalloc(mem, p - pp)))
+ goto_bad;
+
+ if (sscanf(pp, "%s %" PRIu64, s->sync_action, &s->mismatch_count) != 2) {
+ log_error("Failed to parse raid params: %s", params);
+ goto bad;
+ }
+
+ return 1;
+bad:
+ dm_pool_free(mem, s);
+
+ return 0;
+}
+
+static const char *_advance_to_next_word(const char *str, int count)
+{
+ int i;
+ const char *p;
+
+ for (p = str, i = 0; i < count; i++, p++)
+ if (!(p = strchr(p, ' ')))
+ return NULL;
+
+ return p;
+}
+
+/*
+ * <metadata block size> <#used metadata blocks>/<#total metadata blocks>
+ * <cache block size> <#used cache blocks>/<#total cache blocks>
+ * <#read hits> <#read misses> <#write hits> <#write misses>
+ * <#demotions> <#promotions> <#dirty> <#features> <features>*
+ * <#core args> <core args>* <policy name> <#policy args> <policy args>*
+ *
+ * metadata block size : Fixed block size for each metadata block in
+ * sectors
+ * #used metadata blocks : Number of metadata blocks used
+ * #total metadata blocks : Total number of metadata blocks
+ * cache block size : Configurable block size for the cache device
+ * in sectors
+ * #used cache blocks : Number of blocks resident in the cache
+ * #total cache blocks : Total number of cache blocks
+ * #read hits : Number of times a READ bio has been mapped
+ * to the cache
+ * #read misses : Number of times a READ bio has been mapped
+ * to the origin
+ * #write hits : Number of times a WRITE bio has been mapped
+ * to the cache
+ * #write misses : Number of times a WRITE bio has been
+ * mapped to the origin
+ * #demotions : Number of times a block has been removed
+ * from the cache
+ * #promotions : Number of times a block has been moved to
+ * the cache
+ * #dirty : Number of blocks in the cache that differ
+ * from the origin
+ * #feature args : Number of feature args to follow
+ * feature args : 'writethrough' (optional)
+ * #core args : Number of core arguments (must be even)
+ * core args : Key/value pairs for tuning the core
+ * e.g. migration_threshold
+ * *policy name : Name of the policy
+ * #policy args : Number of policy arguments to follow (must be even)
+ * policy args : Key/value pairs
+ * e.g. sequential_threshold
+ */
+int dm_get_status_cache(struct dm_pool *mem, const char *params,
+ struct dm_status_cache **status)
+{
+ int i, feature_argc;
+ char *str;
+ const char *p, *pp;
+ struct dm_status_cache *s;
+
+ if (!(s = dm_pool_zalloc(mem, sizeof(struct dm_status_cache))))
+ return_0;
+
+ /* Read in args that have definitive placement */
+ if (sscanf(params,
+ " %" PRIu32
+ " %" PRIu64 "/%" PRIu64
+ " %" PRIu32
+ " %" PRIu64 "/%" PRIu64
+ " %" PRIu64 " %" PRIu64
+ " %" PRIu64 " %" PRIu64
+ " %" PRIu64 " %" PRIu64
+ " %" PRIu64
+ " %d",
+ &s->metadata_block_size,
+ &s->metadata_used_blocks, &s->metadata_total_blocks,
+ &s->block_size, /* AKA, chunk_size */
+ &s->used_blocks, &s->total_blocks,
+ &s->read_hits, &s->read_misses,
+ &s->write_hits, &s->write_misses,
+ &s->demotions, &s->promotions,
+ &s->dirty_blocks,
+ &feature_argc) != 14)
+ goto bad;
+
+ /* Now jump to "features" section */
+ if (!(p = _advance_to_next_word(params, 12)))
+ goto bad;
+
+ /* Read in features */
+ for (i = 0; i < feature_argc; i++) {
+ if (!strncmp(p, "writethrough ", 13))
+ s->feature_flags |= DM_CACHE_FEATURE_WRITETHROUGH;
+ else if (!strncmp(p, "writeback ", 10))
+ s->feature_flags |= DM_CACHE_FEATURE_WRITEBACK;
+ else
+ log_error("Unknown feature in status: %s", params);
+
+ if (!(p = _advance_to_next_word(p, 1)))
+ goto bad;
+ }
+
+ /* Read in core_args. */
+ if (sscanf(p, "%d ", &s->core_argc) != 1)
+ goto bad;
+ if (s->core_argc &&
+ (!(s->core_argv = dm_pool_zalloc(mem, sizeof(char *) * s->core_argc)) ||
+ !(p = _advance_to_next_word(p, 1)) ||
+ !(str = dm_pool_strdup(mem, p)) ||
+ !(p = _advance_to_next_word(p, s->core_argc)) ||
+ (dm_split_words(str, s->core_argc, 0, s->core_argv) != s->core_argc)))
+ goto bad;
+
+ /* Read in policy args */
+ pp = p;
+ if (!(p = _advance_to_next_word(p, 1)) ||
+ !(s->policy_name = dm_pool_zalloc(mem, (p - pp))))
+ goto bad;
+ if (sscanf(pp, "%s %d", s->policy_name, &s->policy_argc) != 2)
+ goto bad;
+ if (s->policy_argc &&
+ (!(s->policy_argv = dm_pool_zalloc(mem, sizeof(char *) * s->policy_argc)) ||
+ !(p = _advance_to_next_word(p, 1)) ||
+ !(str = dm_pool_strdup(mem, p)) ||
+ (dm_split_words(str, s->policy_argc, 0, s->policy_argv) != s->policy_argc)))
+ goto bad;
+
+ *status = s;
+ return 1;
+
+bad:
+ log_error("Failed to parse cache params: %s", params);
+ dm_pool_free(mem, s);
+ *status = NULL;
+
+ return 0;
+}
+
+int parse_thin_pool_status(const char *params, struct dm_status_thin_pool *s)
+{
+ int pos;
+
+ if (!params) {
+ log_error("Failed to parse invalid thin params.");
+ return 0;
+ }
+
+ /* FIXME: add support for held metadata root */
+ if (sscanf(params, FMTu64 " " FMTu64 "/" FMTu64 " " FMTu64 "/" FMTu64 "%n",
+ &s->transaction_id,
+ &s->used_metadata_blocks,
+ &s->total_metadata_blocks,
+ &s->used_data_blocks,
+ &s->total_data_blocks, &pos) < 5) {
+ log_error("Failed to parse thin pool params: %s.", params);
+ return 0;
+ }
+
+ /* New status flags */
+ if (strstr(params + pos, "no_discard_passdown"))
+ s->discards = DM_THIN_DISCARDS_NO_PASSDOWN;
+ else if (strstr(params + pos, "ignore_discard"))
+ s->discards = DM_THIN_DISCARDS_IGNORE;
+ else /* default discard_passdown */
+ s->discards = DM_THIN_DISCARDS_PASSDOWN;
+
+ if (strstr(params + pos, "ro "))
+ s->read_only = 1;
+ else if (strstr(params + pos, "fail"))
+ s->fail = 1;
+ else if (strstr(params + pos, "out_of_data_space"))
+ s->out_of_data_space = 1;
+
+ if (strstr(params + pos, "error_if_no_space"))
+ s->error_if_no_space = 1;
+
+ return 1;
+}
+
+int dm_get_status_thin_pool(struct dm_pool *mem, const char *params,
+ struct dm_status_thin_pool **status)
+{
+ struct dm_status_thin_pool *s;
+
+ if (!(s = dm_pool_zalloc(mem, sizeof(struct dm_status_thin_pool)))) {
+ log_error("Failed to allocate thin_pool status structure.");
+ return 0;
+ }
+
+ if (!parse_thin_pool_status(params, s)) {
+ dm_pool_free(mem, s);
+ return_0;
+ }
+
+ *status = s;
+
+ return 1;
+}
+
+int dm_get_status_thin(struct dm_pool *mem, const char *params,
+ struct dm_status_thin **status)
+{
+ struct dm_status_thin *s;
+
+ if (!(s = dm_pool_zalloc(mem, sizeof(struct dm_status_thin)))) {
+ log_error("Failed to allocate thin status structure.");
+ return 0;
+ }
+
+ if (strchr(params, '-')) {
+ s->mapped_sectors = 0;
+ s->highest_mapped_sector = 0;
+ } else if (sscanf(params, FMTu64 " " FMTu64,
+ &s->mapped_sectors,
+ &s->highest_mapped_sector) != 2) {
+ dm_pool_free(mem, s);
+ log_error("Failed to parse thin params: %s.", params);
+ return 0;
+ }
+
+ *status = s;
+
+ return 1;
+}