summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBryn M. Reeves <bmr@redhat.com>2016-12-11 13:26:34 +0000
committerBryn M. Reeves <bmr@redhat.com>2016-12-14 19:42:24 +0000
commit7c89429db8e00b85239e4bb8637c9ed2a53ad134 (patch)
tree2abaababebe29ef9ed0ec4d1bcb47ddd3ad18f69
parentd94c4e767832668062eea6085ef5d11055af15a7 (diff)
downloadlvm2-7c89429db8e00b85239e4bb8637c9ed2a53ad134.tar.gz
dmstats: allow --filemap groups to be updated
Add a new update_filemap command to dmstats that allows a filemap group to be updated: # dmstats update_filemap --groupid 0 vm.img /var/lib/libvirt/images/vm.img: Updated group ID 0 with 137 region(s). This will update the set of regions mapped to the file to reflect the current file system allocation. Currently this needs to be run manually - a future update will add support for monitoring file maps via a daemon, allowing them to be automatically updated when the underlying file is modified.
-rw-r--r--tools/dmsetup.c125
1 files changed, 116 insertions, 9 deletions
diff --git a/tools/dmsetup.c b/tools/dmsetup.c
index f0682931f..c3ec29535 100644
--- a/tools/dmsetup.c
+++ b/tools/dmsetup.c
@@ -4958,16 +4958,8 @@ static char *_get_abspath(const char *path)
return _path;
}
-static int _stats_create_file(CMD_ARGS)
+static int _stats_check_filemap_switches(void)
{
- const char *alias, *program_id = DM_STATS_PROGRAM_ID;
- const char *bounds_str = _string_args[BOUNDS_ARG];
- uint64_t *regions, *region, count = 0;
- struct dm_histogram *bounds = NULL;
- char *path, *abspath = NULL;
- struct dm_stats *dms = NULL;
- int group, fd = -1, precise;
-
if (_switches[AREAS_ARG] || _switches[AREA_SIZE_ARG]) {
log_error("--filemap is incompatible with --areas and --area-size.");
return 0;
@@ -4998,6 +4990,27 @@ static int _stats_create_file(CMD_ARGS)
return 0;
}
+ return 1;
+}
+
+static int _stats_create_file(CMD_ARGS)
+{
+ const char *alias, *program_id = DM_STATS_PROGRAM_ID;
+ const char *bounds_str = _string_args[BOUNDS_ARG];
+ uint64_t *regions, *region, count = 0;
+ struct dm_histogram *bounds = NULL;
+ char *path, *abspath = NULL;
+ struct dm_stats *dms = NULL;
+ int group, fd = -1, precise;
+
+ if (names) {
+ err("Device names are not compatibile with --filemap.");
+ return 0;
+ }
+
+ if (!_stats_check_filemap_switches())
+ return 0;
+
/* _stats_create_file does not use _process_all() */
if (!argc) {
log_error("--filemap requires a file path argument");
@@ -5599,6 +5612,99 @@ out:
return r;
}
+static int _stats_update_filemap(CMD_ARGS)
+{
+ uint64_t group_id, *region, *regions, count = 0;
+ const char *program_id = DM_STATS_PROGRAM_ID;
+ struct dm_stats *dms;
+ char *path, *abspath;
+ int fd = -1;
+
+ if (names) {
+ err("Device names are not compatibile with update_filemap.");
+ return 0;
+ }
+
+ if (!_stats_check_filemap_switches())
+ return 0;
+
+ /* _stats_update_filemap does not use _process_all() */
+ if (!argc) {
+ log_error("update_filemap requires a file path argument");
+ return 0;
+ }
+
+ if (!_switches[GROUP_ID_ARG]) {
+ err("--groupid is required to update a filemap group.");
+ return 0;
+ }
+
+ path = argv[0];
+
+ if (!(abspath = _get_abspath(path))) {
+ log_error("Could not canonicalize file name: %s", path);
+ return 0;
+ }
+
+ group_id = (uint64_t) _int_args[GROUP_ID_ARG];
+
+ if (_switches[PROGRAM_ID_ARG])
+ program_id = _string_args[PROGRAM_ID_ARG];
+ if (!strlen(program_id) && !_switches[FORCE_ARG])
+ program_id = DM_STATS_PROGRAM_ID;
+
+ if (!(dms = dm_stats_create(DM_STATS_PROGRAM_ID)))
+ goto_bad;
+
+ fd = open(abspath, O_RDONLY);
+
+ if (fd < 0) {
+ log_error("Could not open %s for reading", abspath);
+ goto bad;
+ }
+
+ if (!_bind_stats_from_fd(dms, fd))
+ goto_bad;
+
+ if (!strlen(program_id))
+ /* force creation of a region with no id */
+ dm_stats_set_program_id(dms, 1, NULL);
+
+ regions = dm_stats_update_regions_from_fd(dms, fd, group_id);
+
+ if (close(fd))
+ log_error("Error closing %s", abspath);
+
+ fd = -1;
+
+ if (!regions) {
+ log_error("Could not update regions from file %s", abspath);
+ goto bad;
+ }
+
+ for (region = regions; *region != DM_STATS_REGIONS_ALL; region++)
+ count++;
+
+ printf("%s: Updated group ID " FMTu64 " with "FMTu64" region(s).\n",
+ path, group_id, count);
+
+ dm_free(regions);
+ dm_free(abspath);
+ dm_stats_destroy(dms);
+ return 1;
+
+bad:
+ dm_free(abspath);
+
+ if ((fd > -1) && close(fd))
+ log_error("Error closing %s", path);
+
+ if (dms)
+ dm_stats_destroy(dms);
+
+ return 0;
+}
+
/*
* Command dispatch tables and usage.
*/
@@ -5640,6 +5746,7 @@ static struct command _stats_subcommands[] = {
{"print", PRINT_OPTS "[<device>]", 0, -1, 1, 0, _stats_print},
{"report", REPORT_OPTS "[<device>]", 0, -1, 1, 0, _stats_report},
{"ungroup", "--groupid <id> [device]", 1, -1, 1, 0, _stats_ungroup},
+ {"update_filemap", "--groupid <id> <file_path>", 1, 1, 0, 0, _stats_update_filemap},
{"version", "", 0, -1, 1, 0, _version},
{NULL, NULL, 0, 0, 0, 0, NULL}
};