diff options
author | Bryn M. Reeves <bmr@redhat.com> | 2016-12-11 13:26:34 +0000 |
---|---|---|
committer | Bryn M. Reeves <bmr@redhat.com> | 2016-12-14 19:42:24 +0000 |
commit | 7c89429db8e00b85239e4bb8637c9ed2a53ad134 (patch) | |
tree | 2abaababebe29ef9ed0ec4d1bcb47ddd3ad18f69 | |
parent | d94c4e767832668062eea6085ef5d11055af15a7 (diff) | |
download | lvm2-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.c | 125 |
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} }; |