diff options
author | Bryn M. Reeves <bmr@redhat.com> | 2016-12-11 13:26:34 +0000 |
---|---|---|
committer | Bryn M. Reeves <bmr@redhat.com> | 2017-01-25 16:15:21 +0000 |
commit | b999d5f501bc959cad138e4a3a2459af90d0a3ca (patch) | |
tree | 23fc926b99a67b6d2aa1ec92e0fea0152bdcb511 | |
parent | e0d19feb85ce8e143c7f107d7bf1c668d667a57c (diff) | |
download | lvm2-b999d5f501bc959cad138e4a3a2459af90d0a3ca.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.c | 131 |
1 files changed, 122 insertions, 9 deletions
diff --git a/tools/dmsetup.c b/tools/dmsetup.c index fabb1830b..c9549c6b5 100644 --- a/tools/dmsetup.c +++ b/tools/dmsetup.c @@ -4957,16 +4957,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; @@ -4997,6 +4989,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"); @@ -5598,6 +5611,105 @@ out: return r; } +static int _stats_update_file(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_file 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 (!dm_stats_bind_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++; + + if (group_id != regions[0]) { + printf("Group ID changed from " FMTu64 " to " FMTu64, + group_id, regions[0]); + group_id = regions[0]; + } + + 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. */ @@ -5678,6 +5790,7 @@ static struct command _stats_subcommands[] = { {"print", PRINT_OPTS, 0, -1, 1, 0, _stats_print}, {"report", REPORT_OPTS "[<device...>]", 0, -1, 1, 0, _stats_report}, {"ungroup", "--groupid <id> " UNGROUP_OPTS, 1, -1, 1, 0, _stats_ungroup}, + {"update_filemap", "--groupid <id> <file_path>", 1, 1, 0, 0, _stats_update_file}, {"version", "", 0, -1, 1, 0, _version}, {NULL, NULL, 0, 0, 0, 0, NULL} }; |