diff --git a/tools/lvchange.c b/tools/lvchange.c index 250d7209b..81dd9ebf1 100644 --- a/tools/lvchange.c +++ b/tools/lvchange.c @@ -25,12 +25,6 @@ static int _lvchange_permission(struct cmd_context *cmd, lv_access = arg_uint_value(cmd, permission_ARG, 0); - if (lv_is_external_origin(lv)) { - log_error("Cannot change permissions of external origin %s.", - display_lvname(lv)); - return 0; - } - if (!(lv_access & LVM_WRITE) && !(lv->status & LVM_WRITE)) { /* Refresh if it's read-only in metadata but read-write in kernel */ if (lv_info(cmd, lv, 0, &info, 0, 0) && info.exists && !info.read_only) { @@ -63,20 +57,6 @@ static int _lvchange_permission(struct cmd_context *cmd, return 0; } - /* Not allowed to change permissions on RAID sub-LVs directly */ - if (lv_is_raid_metadata(lv) || lv_is_raid_image(lv)) { - log_error("Cannot change permissions of RAID %s %s.", - lv_is_raid_image(lv) ? "image" : "metadata area", - display_lvname(lv)); - return 0; - } - - if (!(lv_access & LVM_WRITE) && lv_is_thin_pool(lv)) { - log_error("Change permissions of thin pool %s not yet supported.", - display_lvname(lv)); - return 0; - } - if (lv_access & LVM_WRITE) { lv->status |= LVM_WRITE; log_verbose("Setting logical volume %s read/write.", @@ -100,12 +80,6 @@ static int _lvchange_pool_update(struct cmd_context *cmd, unsigned val; thin_discards_t discards; - if (!lv_is_thin_pool(lv)) { - log_error("Logical volume %s is not a thin pool.", - display_lvname(lv)); - return 0; - } - if (arg_is_set(cmd, discards_ARG)) { discards = (thin_discards_t) arg_uint_value(cmd, discards_ARG, THIN_DISCARDS_IGNORE); if (discards != first_seg(lv)->discards) { @@ -153,10 +127,6 @@ static int _lvchange_monitoring(struct cmd_context *cmd, return 0; } - /* do not monitor pvmove lv's */ - if (lv_is_pvmove(lv)) - return 1; - if ((dmeventd_monitor_mode() != DMEVENTD_MONITOR_IGNORE) && !monitor_dev_for_events(cmd, lv, 0, dmeventd_monitor_mode())) return_0; @@ -280,20 +250,6 @@ static int attach_metadata_devices(struct lv_segment *seg, struct dm_list *list) return 1; } -/* - * lvchange_refresh - * @cmd - * @lv - * - * Suspend and resume a logical volume. - */ -static int _lvchange_refresh(struct cmd_context *cmd, struct logical_volume *lv) -{ - log_verbose("Refreshing logical volume %s (if active).", display_lvname(lv)); - - return lv_refresh(cmd, lv); -} - static int _reactivate_lv(struct logical_volume *lv, int active, int exclusive) { @@ -326,23 +282,6 @@ static int _lvchange_resync(struct cmd_context *cmd, struct logical_volume *lv) dm_list_init(&device_list); - if (seg_is_any_raid0(seg) || - (!seg_is_mirror(seg) && !seg_is_raid(seg))) { - log_error("Unable to resync %s. It is not RAID4/5/6/10 or mirrored.", - display_lvname(lv)); - return 0; - } - - if (lv_is_pvmove(lv)) { - log_error("Unable to resync pvmove volume %s.", display_lvname(lv)); - return 0; - } - - if (lv_is_locked(lv)) { - log_error("Unable to resync locked volume %s.", display_lvname(lv)); - return 0; - } - if (lv_is_active_locally(lv)) { if (!lv_check_not_in_use(lv, 1)) { log_error("Can't resync open logical volume %s.", @@ -691,15 +630,6 @@ static int _lvchange_cache(struct cmd_context *cmd, struct logical_volume *lv) if (lv_is_cache(lv)) pool_seg = first_seg(pool_seg->pool_lv); - else if (!lv_is_cache_pool(lv)) { - log_error("LV %s is not a cache LV.", display_lvname(lv)); - (void) arg_from_list_is_set(cmd, "is supported only with cache or cache pool LVs", - cachemode_ARG, - cachepolicy_ARG, - cachesettings_ARG, - -1); - goto out; - } if (!get_cache_params(cmd, &mode, &name, &settings)) goto_out; @@ -759,12 +689,6 @@ static int _lvchange_rebuild(struct logical_volume *lv) struct arg_value_group_list *group; struct volume_group *vg = lv->vg; struct cmd_context *cmd = vg->cmd; - struct lv_segment *raid_seg = first_seg(lv); - - if (!seg_is_raid(raid_seg) || seg_is_any_raid0(raid_seg)) { - log_error("--rebuild can only be used with 'raid4/5/6/10' segment types."); - return 0; - } if (!(pv_count = arg_count(cmd, rebuild_ARG))) { log_error("No --rebuild found!"); @@ -815,12 +739,6 @@ static int _lvchange_writemostly(struct logical_volume *lv) struct cmd_context *cmd = lv->vg->cmd; struct lv_segment *raid_seg = first_seg(lv); - if (!seg_is_raid1(raid_seg)) { - log_error("--write%s can only be used with 'raid1' segment type.", - arg_is_set(cmd, writemostly_ARG) ? "mostly" : "behind"); - return 0; - } - if (arg_is_set(cmd, writebehind_ARG)) raid_seg->writebehind = arg_uint_value(cmd, writebehind_ARG, 0); @@ -909,12 +827,6 @@ static int _lvchange_recovery_rate(struct logical_volume *lv) struct cmd_context *cmd = lv->vg->cmd; struct lv_segment *raid_seg = first_seg(lv); - if (!seg_is_raid(raid_seg)) { - log_error("Unable to change the recovery rate of non-RAID " - "logical volume %s.", display_lvname(lv)); - return 0; - } - if (arg_is_set(cmd, minrecoveryrate_ARG)) raid_seg->min_recovery_rate = arg_uint_value(cmd, minrecoveryrate_ARG, 0) / 2; @@ -982,114 +894,145 @@ static int _lvchange_activation_skip(struct logical_volume *lv) return 1; } +/* + * For each lvchange command definintion: + * + * lvchange_foo_cmd(cmd, argc, argv); + * . set cmd fields that apply to "foo" + * . set any other things that affect behavior of process_each + * . process_each_lv(_lvchange_foo_single); + * + * _lvchange_foo_single(lv); + * . _lvchange_foo(lv); + * . (or all the code could live in the _single fn) + */ -static int _lvchange_single(struct cmd_context *cmd, struct logical_volume *lv, - struct processing_handle *handle __attribute__((unused))) +static int _lvchange_properties_single(struct cmd_context *cmd, + struct logical_volume *lv, + struct processing_handle *handle) { int doit = 0, docmds = 0; + int i, opt_enum; + + /* + * If a persistent lv lock already exists from activation + * (with the needed mode or higher), this will be a no-op. + * Otherwise, the lv lock will be taken as non-persistent + * and released when this command exits. + */ + if (!lockd_lv(cmd, lv, "ex", 0)) { + stack; + return ECMD_FAILED; + } + + for (i = 0; i < cmd->command->ro_count; i++) { + opt_enum = cmd->command->required_opt_args[i].opt; + + if (!arg_is_set(cmd, opt_enum)) + continue; + + if (!archive(lv->vg)) + return_ECMD_FAILED; + + docmds++; + + switch (opt_enum) { + case permission_ARG: + doit += _lvchange_permission(cmd, lv); + break; + + case alloc_ARG: + case contiguous_ARG: + doit += _lvchange_alloc(cmd, lv); + break; + + case errorwhenfull_ARG: + doit += _lvchange_errorwhenfull(cmd, lv); + break; + + case readahead_ARG: + doit += _lvchange_readahead(cmd, lv); + break; + + case persistent_ARG: + doit += _lvchange_persistent(cmd, lv); + break; + + case discards_ARG: + case zero_ARG: + doit += _lvchange_pool_update(cmd, lv); + break; + + case addtag_ARG: + case deltag_ARG: + doit += _lvchange_tag(cmd, lv, opt_enum); + break; + + case writemostly_ARG: + case writebehind_ARG: + doit += _lvchange_writemostly(lv); + break; + + case minrecoveryrate_ARG: + case maxrecoveryrate_ARG: + doit += _lvchange_recovery_rate(lv); + break; + + case profile_ARG: + case metadataprofile_ARG: + case detachprofile_ARG: + doit += _lvchange_profile(lv); + break; + + case setactivationskip_ARG: + doit += _lvchange_activation_skip(lv); + break; + + case cachemode_ARG: + case cachepolicy_ARG: + case cachesettings_ARG: + doit += _lvchange_cache(cmd, lv); + break; + + default: + log_error(INTERNAL_ERROR "Failed to check for option %s", + arg_long_option_name(i)); + } + } + + if (doit) + log_print_unless_silent("Logical volume %s changed.", display_lvname(lv)); + + if (doit != docmds) + return_ECMD_FAILED; + + return ECMD_PROCESSED; +} + +int lvchange_properties_cmd(struct cmd_context *cmd, int argc, char **argv) +{ + /* + * A command def rule allows only some options when LV is partial, + * so handles_missing_pvs will only affect those. + */ + cmd->handles_missing_pvs = 1; + return process_each_lv(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE, NULL, _lvchange_properties_single); +} + +static int _lvchange_activate_single(struct cmd_context *cmd, + struct logical_volume *lv, + struct processing_handle *handle) +{ struct logical_volume *origin; char snaps_msg[128]; - if (sigint_caught()) - return_ECMD_FAILED; - - if (!(lv->vg->status & LVM_WRITE) && - arg_from_list_is_set(cmd, NULL, - alloc_ARG, - contiguous_ARG, - discards_ARG, - metadataprofile_ARG, - permission_ARG, - persistent_ARG, - profile_ARG, - readahead_ARG, - zero_ARG, - -1)) { - log_error("Only -a permitted with read-only volume group %s.", - lv->vg->name); - return ECMD_FAILED; - } - - if (lv_is_origin(lv) && !lv_is_thin_volume(lv) && - arg_from_list_is_set(cmd, NULL, - alloc_ARG, - contiguous_ARG, - metadataprofile_ARG, - permission_ARG, - persistent_ARG, - profile_ARG, - readahead_ARG, - -1)) { - log_error("Can't change logical volume %s under snapshot.", - display_lvname(lv)); - return ECMD_FAILED; - } - - if (lv_is_pvmove(lv)) { - log_error("Unable to change pvmove LV %s.", display_lvname(lv)); - if (arg_is_set(cmd, activate_ARG)) - log_error("Use 'pvmove --abort' to abandon a pvmove"); - return ECMD_FAILED; - } - - if (lv_is_mirror_log(lv)) { - log_error("Unable to change mirror log LV %s directly.", - display_lvname(lv)); - return ECMD_FAILED; - } - - if (lv_is_mirror_image(lv)) { - log_error("Unable to change mirror image LV %s directly.", - display_lvname(lv)); - return ECMD_FAILED; - } + /* FIXME: untangle the proper logic for cow / sparse / virtual origin */ /* If LV is sparse, activate origin instead */ - if (arg_is_set(cmd, activate_ARG) && lv_is_cow(lv) && - lv_is_virtual_origin(origin = origin_from_cow(lv))) + if (lv_is_cow(lv) && lv_is_virtual_origin(origin = origin_from_cow(lv))) lv = origin; - /* Use cache origin LV for 'raid' actions */ - if (lv_is_cache(lv) && - arg_from_list_is_set(cmd, NULL, - /* FIXME: we want to support more ops here */ - //resync_ARG, - syncaction_ARG, - -1)) { - lv = seg_lv(first_seg(lv), 0); - log_debug("Using cache origin volume %s for lvchange instead.", - display_lvname(lv)); - } - - if ((lv_is_thin_pool_data(lv) || lv_is_thin_pool_metadata(lv) || - lv_is_cache_pool_data(lv) || lv_is_cache_pool_metadata(lv)) && - !arg_is_set(cmd, activate_ARG) && - !arg_is_set(cmd, permission_ARG) && - !arg_is_set(cmd, setactivationskip_ARG)) - /* Rest can be changed for stacked thin pool meta/data volumes */ - ; - else if (lv_is_cache_origin(lv) && lv_is_raid(lv)) { - if (vg_is_clustered(lv->vg)) { - log_error("Unable to change internal LV %s directly in a cluster.", - display_lvname(lv)); - return ECMD_FAILED; - } - /* - * FIXME: For now, we don't want to allow all kinds of - * operations on this cache origin sub-LV. We are going - * to restrict it to non-clustered, RAID. This way, we - * can change the syncaction as needed (e.g. initiate - * scrubbing). - * - * Later pass all 'cache' actions on cache origin. - */ - } else if (!lv_is_visible(lv) && !lv_is_virtual_origin(lv)) { - log_error("Unable to change internal LV %s directly.", - display_lvname(lv)); - return ECMD_FAILED; - } - - if (lv_is_cow(lv) && arg_is_set(cmd, activate_ARG)) { + if (lv_is_cow(lv)) { origin = origin_from_cow(lv); if (origin->origin_count < 2) snaps_msg[0] = '\0'; @@ -1110,294 +1053,6 @@ static int _lvchange_single(struct cmd_context *cmd, struct logical_volume *lv, } } - if (arg_is_set(cmd, errorwhenfull_ARG) && !lv_is_thin_pool(lv)) { - log_error("Option --errorwhenfull is only supported with thin pools."); - return ECMD_FAILED; - } - - if (arg_is_set(cmd, persistent_ARG) && lv_is_pool(lv)) { - log_error("Persistent major and minor numbers are not supported with pools."); - return ECMD_FAILED; - } - - if (!arg_is_set(cmd, activate_ARG) && !arg_is_set(cmd, refresh_ARG)) { - /* - * If a persistent lv lock already exists from activation - * (with the needed mode or higher), this will be a no-op. - * Otherwise, the lv lock will be taken as non-persistent - * and released when this command exits. - * - * FIXME: use "sh" if the options imply that the lvchange - * operation does not modify the LV. - */ - if (!lockd_lv(cmd, lv, "ex", 0)) { - stack; - return ECMD_FAILED; - } - } - - /* - * FIXME: DEFAULT_BACKGROUND_POLLING should be "unspecified". - * If --poll is explicitly provided use it; otherwise polling - * should only be started if the LV is not already active. So: - * 1) change the activation code to say if the LV was actually activated - * 2) make polling of an LV tightly coupled with LV activation - * - * Do not initiate any polling if --sysinit option is used. - */ - init_background_polling(arg_is_set(cmd, sysinit_ARG) ? 0 : - arg_int_value(cmd, poll_ARG, - DEFAULT_BACKGROUND_POLLING)); - - /* access permission change */ - if (arg_is_set(cmd, permission_ARG)) { - if (!archive(lv->vg)) - return_ECMD_FAILED; - doit += _lvchange_permission(cmd, lv); - docmds++; - } - - /* allocation policy change */ - if (arg_is_set(cmd, contiguous_ARG) || arg_is_set(cmd, alloc_ARG)) { - if (!archive(lv->vg)) - return_ECMD_FAILED; - doit += _lvchange_alloc(cmd, lv); - docmds++; - } - - /* error when full change */ - if (arg_is_set(cmd, errorwhenfull_ARG)) { - if (!archive(lv->vg)) - return_ECMD_FAILED; - doit += _lvchange_errorwhenfull(cmd, lv); - docmds++; - } - - /* read ahead sector change */ - if (arg_is_set(cmd, readahead_ARG)) { - if (!archive(lv->vg)) - return_ECMD_FAILED; - doit += _lvchange_readahead(cmd, lv); - docmds++; - } - - /* persistent device number change */ - if (arg_is_set(cmd, persistent_ARG)) { - if (!archive(lv->vg)) - return_ECMD_FAILED; - doit += _lvchange_persistent(cmd, lv); - docmds++; - } - - if (arg_is_set(cmd, discards_ARG) || - arg_is_set(cmd, zero_ARG)) { - if (!archive(lv->vg)) - return_ECMD_FAILED; - doit += _lvchange_pool_update(cmd, lv); - docmds++; - } - - /* add tag */ - if (arg_is_set(cmd, addtag_ARG)) { - if (!archive(lv->vg)) - return_ECMD_FAILED; - doit += _lvchange_tag(cmd, lv, addtag_ARG); - docmds++; - } - - /* del tag */ - if (arg_is_set(cmd, deltag_ARG)) { - if (!archive(lv->vg)) - return_ECMD_FAILED; - doit += _lvchange_tag(cmd, lv, deltag_ARG); - docmds++; - } - - /* rebuild selected PVs */ - if (arg_is_set(cmd, rebuild_ARG)) { - if (!archive(lv->vg)) - return_ECMD_FAILED; - doit += _lvchange_rebuild(lv); - docmds++; - } - - /* change writemostly/writebehind */ - if (arg_is_set(cmd, writemostly_ARG) || arg_is_set(cmd, writebehind_ARG)) { - if (!archive(lv->vg)) - return_ECMD_FAILED; - doit += _lvchange_writemostly(lv); - docmds++; - } - - /* change [min|max]_recovery_rate */ - if (arg_is_set(cmd, minrecoveryrate_ARG) || - arg_is_set(cmd, maxrecoveryrate_ARG)) { - if (!archive(lv->vg)) - return_ECMD_FAILED; - doit += _lvchange_recovery_rate(lv); - docmds++; - } - - /* change configuration profile */ - if (arg_is_set(cmd, profile_ARG) || arg_is_set(cmd, metadataprofile_ARG) || - arg_is_set(cmd, detachprofile_ARG)) { - if (!archive(lv->vg)) - return_ECMD_FAILED; - doit += _lvchange_profile(lv); - docmds++; - } - - if (arg_is_set(cmd, setactivationskip_ARG)) { - if (!archive(lv->vg)) - return_ECMD_FAILED; - doit += _lvchange_activation_skip(lv); - docmds++; - } - - if (arg_is_set(cmd, cachemode_ARG) || - arg_is_set(cmd, cachepolicy_ARG) || arg_is_set(cmd, cachesettings_ARG)) { - if (!archive(lv->vg)) - return_ECMD_FAILED; - doit += _lvchange_cache(cmd, lv); - docmds++; - } - - if (doit) - log_print_unless_silent("Logical volume %s changed.", display_lvname(lv)); - - if (arg_is_set(cmd, resync_ARG) && - !_lvchange_resync(cmd, lv)) - return_ECMD_FAILED; - - if (arg_is_set(cmd, syncaction_ARG)) { - struct lv_segment *seg = first_seg(lv); - - if (seg_is_any_raid0(seg)) { - log_error("Unable to sync raid0 LV %s.", display_lvname(lv)); - return_ECMD_FAILED; - } - - if (!lv_raid_message(lv, arg_str_value(cmd, syncaction_ARG, NULL))) - return_ECMD_FAILED; - } - - /* activation change */ - if (arg_is_set(cmd, activate_ARG)) { - if (!_lvchange_activate(cmd, lv)) - return_ECMD_FAILED; - } else if (arg_is_set(cmd, refresh_ARG)) { - if (!_lvchange_refresh(cmd, lv)) - return_ECMD_FAILED; - } else { - if (arg_is_set(cmd, monitor_ARG) && - !_lvchange_monitoring(cmd, lv)) - return_ECMD_FAILED; - - if (arg_is_set(cmd, poll_ARG) && - !_lvchange_background_polling(cmd, lv)) - return_ECMD_FAILED; - } - - if (doit != docmds) - return_ECMD_FAILED; - - return ECMD_PROCESSED; -} - -int lvchange(struct cmd_context *cmd, int argc, char **argv) -{ - /* - * Options that update metadata should be listed in one of - * the two lists below (i.e. options other than -a, --refresh, - * --monitor or --poll). - */ - int update_partial_safe = /* options safe to update if partial */ - arg_from_list_is_set(cmd, NULL, - addtag_ARG, - contiguous_ARG, - deltag_ARG, - detachprofile_ARG, - metadataprofile_ARG, - permission_ARG, - persistent_ARG, - profile_ARG, - readahead_ARG, - setactivationskip_ARG, - -1); - int update_partial_unsafe = - arg_from_list_is_set(cmd, NULL, - alloc_ARG, - cachemode_ARG, - cachepolicy_ARG, - cachesettings_ARG, - discards_ARG, - errorwhenfull_ARG, - maxrecoveryrate_ARG, - minrecoveryrate_ARG, - rebuild_ARG, - resync_ARG, - syncaction_ARG, - writebehind_ARG, - writemostly_ARG, - zero_ARG, - -1); - int update = update_partial_safe || update_partial_unsafe; - - if (!update && - !arg_is_set(cmd, activate_ARG) && !arg_is_set(cmd, refresh_ARG) && - !arg_is_set(cmd, monitor_ARG) && !arg_is_set(cmd, poll_ARG)) { - log_error("Need 1 or more of -a, -C, -M, -p, -r, -Z, " - "--resync, --refresh, --alloc, --addtag, --deltag, " - "--monitor, --poll or --discards"); - return EINVALID_CMD_LINE; - } - - if ((arg_is_set(cmd, profile_ARG) || arg_is_set(cmd, metadataprofile_ARG)) && - arg_is_set(cmd, detachprofile_ARG)) { - log_error("Only one of --metadataprofile and --detachprofile permitted."); - return EINVALID_CMD_LINE; - } - - if (arg_is_set(cmd, activate_ARG) && arg_is_set(cmd, refresh_ARG)) { - log_error("Only one of -a and --refresh permitted."); - return EINVALID_CMD_LINE; - } - - if ((arg_is_set(cmd, ignorelockingfailure_ARG) || - arg_is_set(cmd, sysinit_ARG)) && update) { - log_error("Only -a permitted with --ignorelockingfailure and --sysinit"); - return EINVALID_CMD_LINE; - } - - if (!update || !update_partial_unsafe) - cmd->handles_missing_pvs = 1; - - if (!argc && !arg_is_set(cmd, select_ARG)) { - log_error("Please give logical volume path(s) or use --select for selection."); - return EINVALID_CMD_LINE; - } - - if ((arg_is_set(cmd, minor_ARG) || arg_is_set(cmd, major_ARG)) && - !arg_is_set(cmd, persistent_ARG)) { - log_error("--major and --minor require -My."); - return EINVALID_CMD_LINE; - } - - if (arg_is_set(cmd, minor_ARG) && argc != 1) { - log_error("Only give one logical volume when specifying minor."); - return EINVALID_CMD_LINE; - } - - if (arg_is_set(cmd, contiguous_ARG) && arg_is_set(cmd, alloc_ARG)) { - log_error("Only one of --alloc and --contiguous permitted."); - return EINVALID_CMD_LINE; - } - - if (arg_is_set(cmd, poll_ARG) && arg_is_set(cmd, sysinit_ARG)) { - log_error("Only one of --poll and --sysinit permitted."); - return EINVALID_CMD_LINE; - } - /* * If --sysinit -aay is used and at the same time lvmetad is used, * we want to rely on autoactivation to take place. Also, we @@ -1412,27 +1067,137 @@ int lvchange(struct cmd_context *cmd, int argc, char **argv) } } + if (!_lvchange_activate(cmd, lv)) + return_ECMD_FAILED; + + return ECMD_PROCESSED; +} + +int lvchange_activate_cmd(struct cmd_context *cmd, int argc, char **argv) +{ + cmd->handles_missing_pvs = 1; + cmd->lockd_vg_default_sh = 1; + /* * Include foreign VGs that contain active LVs. * That shouldn't happen in general, but if it does by some * mistake, then we want to allow those LVs to be deactivated. */ - if (arg_is_set(cmd, activate_ARG)) - cmd->include_active_foreign_vgs = 1; + cmd->include_active_foreign_vgs = 1; - /* - * The default vg lock mode for lvchange is ex, but these options - * are cases where lvchange does not modify the vg, so they can use - * the sh lock mode. - */ - if (arg_is_set(cmd, activate_ARG) || arg_is_set(cmd, refresh_ARG)) { - cmd->lockd_vg_default_sh = 1; - /* Allow deactivating if locks fail. */ - if (is_change_activating((activation_change_t)arg_uint_value(cmd, activate_ARG, CHANGE_AY))) - cmd->lockd_vg_enforce_sh = 1; - } + /* Allow deactivating if locks fail. */ + if (is_change_activating((activation_change_t)arg_uint_value(cmd, activate_ARG, CHANGE_AY))) + cmd->lockd_vg_enforce_sh = 1; - return process_each_lv(cmd, argc, argv, NULL, NULL, - update ? READ_FOR_UPDATE : 0, NULL, - &_lvchange_single); + return process_each_lv(cmd, argc, argv, NULL, NULL, 0, NULL, _lvchange_activate_single); } + +static int _lvchange_refresh_single(struct cmd_context *cmd, + struct logical_volume *lv, + struct processing_handle *handle) +{ + log_verbose("Refreshing logical volume %s (if active).", display_lvname(lv)); + + if (!lv_refresh(cmd, lv)) + return_ECMD_FAILED; + + return ECMD_PROCESSED; +} + +int lvchange_refresh_cmd(struct cmd_context *cmd, int argc, char **argv) +{ + cmd->handles_missing_pvs = 1; + cmd->lockd_vg_default_sh = 1; + + return process_each_lv(cmd, argc, argv, NULL, NULL, 0, NULL, _lvchange_refresh_single); +} + +static int _lvchange_resync_single(struct cmd_context *cmd, + struct logical_volume *lv, + struct processing_handle *handle) +{ + if (!_lvchange_resync(cmd, lv)) + return_ECMD_FAILED; + + return ECMD_PROCESSED; +} + +int lvchange_resync_cmd(struct cmd_context *cmd, int argc, char **argv) +{ + return process_each_lv(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE, NULL, _lvchange_resync_single); +} + +static int _lvchange_syncaction_single(struct cmd_context *cmd, + struct logical_volume *lv, + struct processing_handle *handle) +{ + if (!lv_raid_message(lv, arg_str_value(cmd, syncaction_ARG, NULL))) + return_ECMD_FAILED; + + return ECMD_PROCESSED; +} + +int lvchange_syncaction_cmd(struct cmd_context *cmd, int argc, char **argv) +{ + return process_each_lv(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE, NULL, _lvchange_syncaction_single); +} + +static int _lvchange_rebuild_single(struct cmd_context *cmd, + struct logical_volume *lv, + struct processing_handle *handle) +{ + if (!_lvchange_rebuild(lv)) + return_ECMD_FAILED; + + return ECMD_PROCESSED; +} + +int lvchange_rebuild_cmd(struct cmd_context *cmd, int argc, char **argv) +{ + return process_each_lv(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE, NULL, _lvchange_rebuild_single); +} + +static int _lvchange_monitor_poll_single(struct cmd_context *cmd, + struct logical_volume *lv, + struct processing_handle *handle) +{ + if (arg_is_set(cmd, monitor_ARG) && + !_lvchange_monitoring(cmd, lv)) + return_ECMD_FAILED; + + if (arg_is_set(cmd, poll_ARG) && + !_lvchange_background_polling(cmd, lv)) + return_ECMD_FAILED; + + return ECMD_PROCESSED; +} + +int lvchange_monitor_poll_cmd(struct cmd_context *cmd, int argc, char **argv) +{ + cmd->handles_missing_pvs = 1; + return process_each_lv(cmd, argc, argv, NULL, NULL, 0, NULL, _lvchange_monitor_poll_single); +} + +static int _lvchange_persistent_single(struct cmd_context *cmd, + struct logical_volume *lv, + struct processing_handle *handle) +{ + if (!_lvchange_persistent(cmd, lv)) + return_ECMD_FAILED; + + return ECMD_PROCESSED; +} + +int lvchange_persistent_cmd(struct cmd_context *cmd, int argc, char **argv) +{ + cmd->handles_missing_pvs = 1; + return process_each_lv(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE, NULL, _lvchange_persistent_single); +} + +int lvchange(struct cmd_context *cmd, int argc, char **argv) +{ + log_error(INTERNAL_ERROR "Missing function for command definition %s.", + cmd->command->command_line_id); + return ECMD_FAILED; +} + diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c index a48830340..d88a06199 100644 --- a/tools/lvmcmdline.c +++ b/tools/lvmcmdline.c @@ -113,6 +113,15 @@ static struct cmdline_context _cmdline; */ struct command_function command_functions[COMMAND_ID_COUNT] = { { lvmconfig_general_CMD, lvmconfig }, + { lvchange_properties_CMD, lvchange_properties_cmd }, + { lvchange_resync_CMD, lvchange_resync_cmd }, + { lvchange_syncaction_CMD, lvchange_syncaction_cmd }, + { lvchange_rebuild_CMD, lvchange_rebuild_cmd }, + { lvchange_activate_CMD, lvchange_activate_cmd }, + { lvchange_refresh_CMD, lvchange_refresh_cmd }, + { lvchange_monitor_CMD, lvchange_monitor_poll_cmd }, + { lvchange_poll_CMD, lvchange_monitor_poll_cmd }, + { lvchange_persistent_CMD, lvchange_persistent_cmd }, }; #if 0 /* all raid-related type conversions */ diff --git a/tools/tools.h b/tools/tools.h index 5efa546c9..fbf19fefd 100644 --- a/tools/tools.h +++ b/tools/tools.h @@ -241,4 +241,13 @@ int vgchange_background_polling(struct cmd_context *cmd, struct volume_group *vg struct lv_props *get_lv_prop(int lvp_enum); struct lv_types *get_lv_type(int lvt_enum); +int lvchange_properties_cmd(struct cmd_context *cmd, int argc, char **argv); +int lvchange_activate_cmd(struct cmd_context *cmd, int argc, char **argv); +int lvchange_refresh_cmd(struct cmd_context *cmd, int argc, char **argv); +int lvchange_resync_cmd(struct cmd_context *cmd, int argc, char **argv); +int lvchange_syncaction_cmd(struct cmd_context *cmd, int argc, char **argv); +int lvchange_rebuild_cmd(struct cmd_context *cmd, int argc, char **argv); +int lvchange_monitor_poll_cmd(struct cmd_context *cmd, int argc, char **argv); +int lvchange_persistent_cmd(struct cmd_context *cmd, int argc, char **argv); + #endif