mirror of
				git://sourceware.org/git/lvm2.git
				synced 2025-10-29 16:23:49 +03:00 
			
		
		
		
	Compare commits
	
		
			81 Commits
		
	
	
		
			dev-dct-cm
			...
			sourceware
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 8ab0725077 | ||
|  | 3f4ecaf8c2 | ||
|  | da634bfc89 | ||
|  | 1eb1869626 | ||
|  | aa72caca5a | ||
|  | f44e69f9fc | ||
|  | 9712995edd | ||
|  | 6716f5a2f4 | ||
|  | 263050bc07 | ||
|  | c1ce371b59 | ||
|  | b7ae57c6a6 | ||
|  | 21fc35dd1b | ||
|  | 7e411b111f | ||
|  | f80d373753 | ||
|  | d2dbe71fb3 | ||
|  | 1c1ce2739e | ||
|  | 2a65e2d49e | ||
|  | 7c14004f69 | ||
|  | d409fec079 | ||
|  | 921d5972e8 | ||
|  | 86a660be7b | ||
|  | e13639053b | ||
|  | d22cccdf63 | ||
|  | a2d2cd8777 | ||
|  | 2396c50689 | ||
|  | 4d29d9afb2 | ||
|  | 5f2639d01d | ||
|  | 13dd1ca757 | ||
|  | 2260c6d1e6 | ||
|  | d8514b24e1 | ||
|  | aff62c74b7 | ||
|  | f16ad760cb | ||
|  | cd24e6de89 | ||
|  | 665479b818 | ||
|  | 2a21a19d90 | ||
|  | 87c89ac279 | ||
|  | 13944738d4 | ||
|  | fab0d63121 | ||
|  | 87fe9328d3 | ||
|  | 6064b0359a | ||
|  | 50e0345f9d | ||
|  | 10cb8e0ec0 | ||
|  | 3cf3943898 | ||
|  | f88ce5fb99 | ||
|  | 56deed9d54 | ||
|  | 00f299b932 | ||
|  | 238a79aac4 | ||
|  | 995f7aa92f | ||
|  | 46d6c7d3ad | ||
|  | 772834e40a | ||
|  | 582a272b3f | ||
|  | 80b717af0c | ||
|  | 298b11aed1 | ||
|  | 1cb95fa5a0 | ||
|  | 15f51bc421 | ||
|  | 22bee4fbdb | ||
|  | 81c0ed9fc6 | ||
|  | 6a5c9ba349 | ||
|  | 2556498ee1 | ||
|  | 4a30f5f9b0 | ||
|  | 286d39ee3c | ||
|  | d3af0e7528 | ||
|  | 7417c8acfa | ||
|  | d2c5bb5c70 | ||
|  | 1236e0ed29 | ||
|  | 1dddb068c9 | ||
|  | c0f2a59993 | ||
|  | f46b28bdb6 | ||
|  | c868562a79 | ||
|  | 22457ed4d9 | ||
|  | fc0e49297d | ||
|  | 3350eb67cc | ||
|  | 6118b0fb93 | ||
|  | 65b82a8072 | ||
|  | 05dd566a52 | ||
|  | 5a87d8667d | ||
|  | 5ab051df7a | ||
|  | c816e8b636 | ||
|  | 717363bb94 | ||
|  | b2fd5b31d3 | ||
|  | 698abdde16 | 
| @@ -59,6 +59,8 @@ liblvm: lib | ||||
| daemons: lib libdaemon tools | ||||
| tools: lib libdaemon device-mapper | ||||
| po: tools daemons | ||||
| man: tools | ||||
| all_man: tools | ||||
| scripts: liblvm libdm | ||||
|  | ||||
| lib.device-mapper: include.device-mapper | ||||
|   | ||||
							
								
								
									
										14
									
								
								WHATS_NEW
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								WHATS_NEW
									
									
									
									
									
								
							| @@ -1,5 +1,19 @@ | ||||
| Version 2.02.169 -  | ||||
| ===================================== | ||||
|   Reject writemostly/writebehind in lvchange during resynchronization. | ||||
|   Deactivate active origin first before removal for improved workflow. | ||||
|   Fix regression of accepting options --type and -m with lvresize (2.02.158). | ||||
|   Add lvconvert --swapmetadata, new specific way to swap pool metadata LVs. | ||||
|   Add lvconvert --startpoll, new specific way to start polling conversions. | ||||
|   Add lvconvert --mergethin, new specific way to merge thin snapshots. | ||||
|   Add lvconvert --mergemirrors, new specific way to merge split mirrors. | ||||
|   Add lvconvert --mergesnapshot, new specific way to combine cow LVs. | ||||
|   Split up lvconvert code based on command definitions. | ||||
|   Split up lvchange code based on command definitions. | ||||
|   Generate help output and man pages from command definitions. | ||||
|   Verify all command line items against command definition. | ||||
|   Match every command run to one command definition. | ||||
|   Specify every allowed command definition/syntax in command-lines.in. | ||||
|   Add extra memory page when limiting pthread stack size in clvmd. | ||||
|   Support striped/raid0* <-> raid10_near conversions | ||||
|   Support shrinking of RaidLvs | ||||
|   | ||||
							
								
								
									
										198
									
								
								configure
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										198
									
								
								configure
									
									
									
									
										vendored
									
									
								
							| @@ -821,6 +821,8 @@ HAVE_PIE | ||||
| POW_LIB | ||||
| LIBOBJS | ||||
| ALLOCA | ||||
| SORT | ||||
| WC | ||||
| CHMOD | ||||
| CSCOPE_CMD | ||||
| CFLOW_CMD | ||||
| @@ -5234,6 +5236,202 @@ else | ||||
|   CHMOD="$ac_cv_path_CHMOD" | ||||
| fi | ||||
|  | ||||
| if test -n "$ac_tool_prefix"; then | ||||
|   # Extract the first word of "${ac_tool_prefix}wc", so it can be a program name with args. | ||||
| set dummy ${ac_tool_prefix}wc; ac_word=$2 | ||||
| { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 | ||||
| $as_echo_n "checking for $ac_word... " >&6; } | ||||
| if ${ac_cv_path_WC+:} false; then : | ||||
|   $as_echo_n "(cached) " >&6 | ||||
| else | ||||
|   case $WC in | ||||
|   [\\/]* | ?:[\\/]*) | ||||
|   ac_cv_path_WC="$WC" # Let the user override the test with a path. | ||||
|   ;; | ||||
|   *) | ||||
|   as_save_IFS=$IFS; IFS=$PATH_SEPARATOR | ||||
| for as_dir in $PATH | ||||
| do | ||||
|   IFS=$as_save_IFS | ||||
|   test -z "$as_dir" && as_dir=. | ||||
|     for ac_exec_ext in '' $ac_executable_extensions; do | ||||
|   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then | ||||
|     ac_cv_path_WC="$as_dir/$ac_word$ac_exec_ext" | ||||
|     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 | ||||
|     break 2 | ||||
|   fi | ||||
| done | ||||
|   done | ||||
| IFS=$as_save_IFS | ||||
|  | ||||
|   ;; | ||||
| esac | ||||
| fi | ||||
| WC=$ac_cv_path_WC | ||||
| if test -n "$WC"; then | ||||
|   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WC" >&5 | ||||
| $as_echo "$WC" >&6; } | ||||
| else | ||||
|   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 | ||||
| $as_echo "no" >&6; } | ||||
| fi | ||||
|  | ||||
|  | ||||
| fi | ||||
| if test -z "$ac_cv_path_WC"; then | ||||
|   ac_pt_WC=$WC | ||||
|   # Extract the first word of "wc", so it can be a program name with args. | ||||
| set dummy wc; ac_word=$2 | ||||
| { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 | ||||
| $as_echo_n "checking for $ac_word... " >&6; } | ||||
| if ${ac_cv_path_ac_pt_WC+:} false; then : | ||||
|   $as_echo_n "(cached) " >&6 | ||||
| else | ||||
|   case $ac_pt_WC in | ||||
|   [\\/]* | ?:[\\/]*) | ||||
|   ac_cv_path_ac_pt_WC="$ac_pt_WC" # Let the user override the test with a path. | ||||
|   ;; | ||||
|   *) | ||||
|   as_save_IFS=$IFS; IFS=$PATH_SEPARATOR | ||||
| for as_dir in $PATH | ||||
| do | ||||
|   IFS=$as_save_IFS | ||||
|   test -z "$as_dir" && as_dir=. | ||||
|     for ac_exec_ext in '' $ac_executable_extensions; do | ||||
|   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then | ||||
|     ac_cv_path_ac_pt_WC="$as_dir/$ac_word$ac_exec_ext" | ||||
|     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 | ||||
|     break 2 | ||||
|   fi | ||||
| done | ||||
|   done | ||||
| IFS=$as_save_IFS | ||||
|  | ||||
|   ;; | ||||
| esac | ||||
| fi | ||||
| ac_pt_WC=$ac_cv_path_ac_pt_WC | ||||
| if test -n "$ac_pt_WC"; then | ||||
|   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_WC" >&5 | ||||
| $as_echo "$ac_pt_WC" >&6; } | ||||
| else | ||||
|   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 | ||||
| $as_echo "no" >&6; } | ||||
| fi | ||||
|  | ||||
|   if test "x$ac_pt_WC" = x; then | ||||
|     WC="" | ||||
|   else | ||||
|     case $cross_compiling:$ac_tool_warned in | ||||
| yes:) | ||||
| { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 | ||||
| $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} | ||||
| ac_tool_warned=yes ;; | ||||
| esac | ||||
|     WC=$ac_pt_WC | ||||
|   fi | ||||
| else | ||||
|   WC="$ac_cv_path_WC" | ||||
| fi | ||||
|  | ||||
| if test -n "$ac_tool_prefix"; then | ||||
|   # Extract the first word of "${ac_tool_prefix}sort", so it can be a program name with args. | ||||
| set dummy ${ac_tool_prefix}sort; ac_word=$2 | ||||
| { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 | ||||
| $as_echo_n "checking for $ac_word... " >&6; } | ||||
| if ${ac_cv_path_SORT+:} false; then : | ||||
|   $as_echo_n "(cached) " >&6 | ||||
| else | ||||
|   case $SORT in | ||||
|   [\\/]* | ?:[\\/]*) | ||||
|   ac_cv_path_SORT="$SORT" # Let the user override the test with a path. | ||||
|   ;; | ||||
|   *) | ||||
|   as_save_IFS=$IFS; IFS=$PATH_SEPARATOR | ||||
| for as_dir in $PATH | ||||
| do | ||||
|   IFS=$as_save_IFS | ||||
|   test -z "$as_dir" && as_dir=. | ||||
|     for ac_exec_ext in '' $ac_executable_extensions; do | ||||
|   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then | ||||
|     ac_cv_path_SORT="$as_dir/$ac_word$ac_exec_ext" | ||||
|     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 | ||||
|     break 2 | ||||
|   fi | ||||
| done | ||||
|   done | ||||
| IFS=$as_save_IFS | ||||
|  | ||||
|   ;; | ||||
| esac | ||||
| fi | ||||
| SORT=$ac_cv_path_SORT | ||||
| if test -n "$SORT"; then | ||||
|   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SORT" >&5 | ||||
| $as_echo "$SORT" >&6; } | ||||
| else | ||||
|   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 | ||||
| $as_echo "no" >&6; } | ||||
| fi | ||||
|  | ||||
|  | ||||
| fi | ||||
| if test -z "$ac_cv_path_SORT"; then | ||||
|   ac_pt_SORT=$SORT | ||||
|   # Extract the first word of "sort", so it can be a program name with args. | ||||
| set dummy sort; ac_word=$2 | ||||
| { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 | ||||
| $as_echo_n "checking for $ac_word... " >&6; } | ||||
| if ${ac_cv_path_ac_pt_SORT+:} false; then : | ||||
|   $as_echo_n "(cached) " >&6 | ||||
| else | ||||
|   case $ac_pt_SORT in | ||||
|   [\\/]* | ?:[\\/]*) | ||||
|   ac_cv_path_ac_pt_SORT="$ac_pt_SORT" # Let the user override the test with a path. | ||||
|   ;; | ||||
|   *) | ||||
|   as_save_IFS=$IFS; IFS=$PATH_SEPARATOR | ||||
| for as_dir in $PATH | ||||
| do | ||||
|   IFS=$as_save_IFS | ||||
|   test -z "$as_dir" && as_dir=. | ||||
|     for ac_exec_ext in '' $ac_executable_extensions; do | ||||
|   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then | ||||
|     ac_cv_path_ac_pt_SORT="$as_dir/$ac_word$ac_exec_ext" | ||||
|     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 | ||||
|     break 2 | ||||
|   fi | ||||
| done | ||||
|   done | ||||
| IFS=$as_save_IFS | ||||
|  | ||||
|   ;; | ||||
| esac | ||||
| fi | ||||
| ac_pt_SORT=$ac_cv_path_ac_pt_SORT | ||||
| if test -n "$ac_pt_SORT"; then | ||||
|   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_SORT" >&5 | ||||
| $as_echo "$ac_pt_SORT" >&6; } | ||||
| else | ||||
|   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 | ||||
| $as_echo "no" >&6; } | ||||
| fi | ||||
|  | ||||
|   if test "x$ac_pt_SORT" = x; then | ||||
|     SORT="" | ||||
|   else | ||||
|     case $cross_compiling:$ac_tool_warned in | ||||
| yes:) | ||||
| { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 | ||||
| $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} | ||||
| ac_tool_warned=yes ;; | ||||
| esac | ||||
|     SORT=$ac_pt_SORT | ||||
|   fi | ||||
| else | ||||
|   SORT="$ac_cv_path_SORT" | ||||
| fi | ||||
|  | ||||
|  | ||||
| ################################################################################ | ||||
| ac_header_dirent=no | ||||
|   | ||||
| @@ -86,6 +86,8 @@ AC_PROG_RANLIB | ||||
| AC_PATH_TOOL(CFLOW_CMD, cflow) | ||||
| AC_PATH_TOOL(CSCOPE_CMD, cscope) | ||||
| AC_PATH_TOOL(CHMOD, chmod) | ||||
| AC_PATH_TOOL(WC, wc) | ||||
| AC_PATH_TOOL(SORT, sort) | ||||
|  | ||||
| ################################################################################ | ||||
| dnl -- Check for header files. | ||||
|   | ||||
| @@ -184,16 +184,12 @@ int register_device(const char *device, | ||||
| 		goto_bad; | ||||
|  | ||||
| 	if (!dmeventd_lvm2_command(state->mem, state->cmd_lvscan, sizeof(state->cmd_lvscan), | ||||
| 				   "lvscan --cache", device)) { | ||||
| 		dmeventd_lvm2_exit_with_pool(state); | ||||
| 				   "lvscan --cache", device)) | ||||
| 		goto_bad; | ||||
| 	} | ||||
|  | ||||
| 	if (!dmeventd_lvm2_command(state->mem, state->cmd_lvconvert, sizeof(state->cmd_lvconvert), | ||||
| 				   "lvconvert --repair --use-policies", device)) { | ||||
| 		dmeventd_lvm2_exit_with_pool(state); | ||||
| 				   "lvconvert --repair --use-policies", device)) | ||||
| 		goto_bad; | ||||
| 	} | ||||
|  | ||||
| 	*user = state; | ||||
|  | ||||
| @@ -203,6 +199,9 @@ int register_device(const char *device, | ||||
| bad: | ||||
| 	log_error("Failed to monitor mirror %s.", device); | ||||
|  | ||||
| 	if (state) | ||||
| 		dmeventd_lvm2_exit_with_pool(state); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -140,10 +140,8 @@ int register_device(const char *device, | ||||
| 				   "lvscan --cache", device) || | ||||
| 	    !dmeventd_lvm2_command(state->mem, state->cmd_lvconvert, sizeof(state->cmd_lvconvert), | ||||
| 				   "lvconvert --config devices{ignore_suspended_devices=1} " | ||||
| 				   "--repair --use-policies", device)) { | ||||
| 		dmeventd_lvm2_exit_with_pool(state); | ||||
| 				   "--repair --use-policies", device)) | ||||
| 		goto_bad; | ||||
| 	} | ||||
|  | ||||
| 	*user = state; | ||||
|  | ||||
| @@ -153,6 +151,9 @@ int register_device(const char *device, | ||||
| bad: | ||||
| 	log_error("Failed to monitor RAID %s.", device); | ||||
|  | ||||
| 	if (state) | ||||
| 		dmeventd_lvm2_exit_with_pool(state); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -254,10 +254,8 @@ int register_device(const char *device, | ||||
|  | ||||
| 	if (!dmeventd_lvm2_command(state->mem, state->cmd_lvextend, | ||||
| 				   sizeof(state->cmd_lvextend), | ||||
| 				   "lvextend --use-policies", device)) { | ||||
| 		dmeventd_lvm2_exit_with_pool(state); | ||||
| 				   "lvextend --use-policies", device)) | ||||
| 		goto_bad; | ||||
| 	} | ||||
|  | ||||
| 	state->percent_check = CHECK_MINIMUM; | ||||
| 	*user = state; | ||||
| @@ -268,6 +266,9 @@ int register_device(const char *device, | ||||
| bad: | ||||
| 	log_error("Failed to monitor snapshot %s.", device); | ||||
|  | ||||
| 	if (state) | ||||
| 		dmeventd_lvm2_exit_with_pool(state); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -359,10 +359,8 @@ int register_device(const char *device, | ||||
| 		goto_bad; | ||||
|  | ||||
| 	if (!dmeventd_lvm2_command(state->mem, cmd_str, sizeof(cmd_str), | ||||
| 				   "_dmeventd_thin_command", device)) { | ||||
| 		dmeventd_lvm2_exit_with_pool(state); | ||||
| 				   "_dmeventd_thin_command", device)) | ||||
| 		goto_bad; | ||||
| 	} | ||||
|  | ||||
| 	if (strncmp(cmd_str, "lvm ", 4) == 0) { | ||||
| 		if (!(state->cmd_str = dm_pool_strdup(state->mem, cmd_str + 4))) { | ||||
| @@ -401,6 +399,9 @@ inval: | ||||
| bad: | ||||
| 	log_error("Failed to monitor thin pool %s.", device); | ||||
|  | ||||
| 	if (state) | ||||
| 		dmeventd_lvm2_exit_with_pool(state); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1948,16 +1948,13 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume | ||||
|  | ||||
| 		/* Check [un]monitor results */ | ||||
| 		/* Try a couple times if pending, but not forever... */ | ||||
| 		for (i = 0; i < 40; i++) { | ||||
| 		for (i = 0;; i++) { | ||||
| 			pending = 0; | ||||
| 			monitored = seg->segtype->ops->target_monitored(seg, &pending); | ||||
| 			if (pending || | ||||
| 			    (!monitored && monitor) || | ||||
| 			    (monitored && !monitor)) | ||||
| 				log_very_verbose("%s %smonitoring still pending: waiting...", | ||||
| 						 display_lvname(lv), monitor ? "" : "un"); | ||||
| 			else | ||||
| 			if (!pending || i >= 40) | ||||
| 				break; | ||||
| 			log_very_verbose("%s %smonitoring still pending: waiting...", | ||||
| 					 display_lvname(lv), monitor ? "" : "un"); | ||||
| 			usleep(10000 * i); | ||||
| 		} | ||||
|  | ||||
|   | ||||
| @@ -6229,12 +6229,21 @@ int lv_remove_with_dependencies(struct cmd_context *cmd, struct logical_volume * | ||||
| 		/* Remove snapshot LVs first */ | ||||
| 		if ((force == PROMPT) && | ||||
| 		    /* Active snapshot already needs to confirm each active LV */ | ||||
| 		    !lv_is_active(lv) && | ||||
| 		    yes_no_prompt("Removing origin %s will also remove %u " | ||||
| 				  "snapshots(s). Proceed? [y/n]: ", | ||||
| 				  lv->name, lv->origin_count) == 'n') | ||||
| 		    (yes_no_prompt("Do you really want to remove%s " | ||||
| 				   "%sorigin logical volume %s with %u snapshot(s)? [y/n]: ", | ||||
| 				   lv_is_active(lv) ? " active" : "", | ||||
| 				   vg_is_clustered(lv->vg) ? "clustered " : "", | ||||
| 				   display_lvname(lv), | ||||
| 				   lv->origin_count) == 'n')) | ||||
| 			goto no_remove; | ||||
|  | ||||
| 		if (!deactivate_lv(cmd, lv)) { | ||||
| 			stack; | ||||
| 			goto no_remove; | ||||
| 		} | ||||
| 		log_verbose("Removing origin logical volume %s with %u snapshots(s).", | ||||
| 			    display_lvname(lv), lv->origin_count); | ||||
|  | ||||
| 		dm_list_iterate_safe(snh, snht, &lv->snapshot_segs) | ||||
| 			if (!lv_remove_with_dependencies(cmd, dm_list_struct_base(snh, struct lv_segment, | ||||
| 										  origin_list)->cow, | ||||
|   | ||||
| @@ -1232,6 +1232,7 @@ uint32_t raid_rimage_extents(const struct segment_type *segtype, | ||||
| uint32_t raid_ensure_min_region_size(const struct logical_volume *lv, uint64_t raid_size, uint32_t region_size); | ||||
| int lv_raid_change_region_size(struct logical_volume *lv, | ||||
|                                int yes, int force, uint32_t new_region_size); | ||||
| int lv_raid_in_sync(const struct logical_volume *lv); | ||||
| /* --  metadata/raid_manip.c */ | ||||
|  | ||||
| /* ++  metadata/cache_manip.c */ | ||||
|   | ||||
| @@ -238,7 +238,7 @@ static int _deactivate_and_remove_lvs(struct volume_group *vg, struct dm_list *r | ||||
|  * Returns: 1 if in-sync, 0 otherwise. | ||||
|  */ | ||||
| #define _RAID_IN_SYNC_RETRIES  6 | ||||
| static int _raid_in_sync(struct logical_volume *lv) | ||||
| static int _raid_in_sync(const struct logical_volume *lv) | ||||
| { | ||||
| 	int retries = _RAID_IN_SYNC_RETRIES; | ||||
| 	dm_percent_t sync_percent; | ||||
| @@ -269,6 +269,12 @@ static int _raid_in_sync(struct logical_volume *lv) | ||||
| 	return (sync_percent == DM_PERCENT_100) ? 1 : 0; | ||||
| } | ||||
|  | ||||
| /* External interface to raid in-sync check */ | ||||
| int lv_raid_in_sync(const struct logical_volume *lv) | ||||
| { | ||||
| 	return _raid_in_sync(lv); | ||||
| } | ||||
|  | ||||
| /* Check if RaidLV @lv is synced or any raid legs of @lv are not synced */ | ||||
| static int _raid_devs_sync_healthy(struct logical_volume *lv) | ||||
| { | ||||
|   | ||||
| @@ -3868,37 +3868,6 @@ static int _extent_start_compare(const void *p1, const void *p2) | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Resize the group bitmap corresponding to group_id so that it can | ||||
|  * contain at least num_regions members. | ||||
|  */ | ||||
| static int _stats_resize_group(struct dm_stats_group *group, int num_regions) | ||||
| { | ||||
| 	int last_bit = dm_bit_get_last(group->regions); | ||||
| 	dm_bitset_t new, old; | ||||
|  | ||||
| 	if (last_bit >= num_regions) { | ||||
| 		log_error("Cannot resize group bitmap to %d with bit %d set.", | ||||
| 			  num_regions, last_bit); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	log_very_verbose("Resizing group bitmap from %d to %d (last_bit: %d).", | ||||
| 			 group->regions[0], num_regions, last_bit); | ||||
|  | ||||
| 	new = dm_bitset_create(NULL, num_regions); | ||||
| 	if (!new) { | ||||
| 		log_error("Could not allocate memory for new group bitmap."); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	old = group->regions; | ||||
| 	dm_bit_copy(new, old); | ||||
| 	group->regions = new; | ||||
| 	dm_bitset_destroy(old); | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| static int _stats_create_group(struct dm_stats *dms, dm_bitset_t regions, | ||||
| 			       const char *alias, uint64_t *group_id) | ||||
| { | ||||
| @@ -4202,6 +4171,37 @@ int dm_stats_get_group_descriptor(const struct dm_stats *dms, | ||||
| } | ||||
|  | ||||
| #ifdef HAVE_LINUX_FIEMAP_H | ||||
| /* | ||||
|  * Resize the group bitmap corresponding to group_id so that it can | ||||
|  * contain at least num_regions members. | ||||
|  */ | ||||
| static int _stats_resize_group(struct dm_stats_group *group, int num_regions) | ||||
| { | ||||
| 	int last_bit = dm_bit_get_last(group->regions); | ||||
| 	dm_bitset_t new, old; | ||||
|  | ||||
| 	if (last_bit >= num_regions) { | ||||
| 		log_error("Cannot resize group bitmap to %d with bit %d set.", | ||||
| 			  num_regions, last_bit); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	log_very_verbose("Resizing group bitmap from %d to %d (last_bit: %d).", | ||||
| 			 group->regions[0], num_regions, last_bit); | ||||
|  | ||||
| 	new = dm_bitset_create(NULL, num_regions); | ||||
| 	if (!new) { | ||||
| 		log_error("Could not allocate memory for new group bitmap."); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	old = group->regions; | ||||
| 	dm_bit_copy(new, old); | ||||
| 	group->regions = new; | ||||
| 	dm_bitset_destroy(old); | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Group a table of region_ids corresponding to the extents of a file. | ||||
|  */ | ||||
|   | ||||
| @@ -40,6 +40,11 @@ SED = @SED@ | ||||
| CFLOW_CMD = @CFLOW_CMD@ | ||||
| AWK = @AWK@ | ||||
| CHMOD = @CHMOD@ | ||||
| EGREP = @EGREP@ | ||||
| GREP = @GREP@ | ||||
| SORT = @SORT@ | ||||
| WC = @WC@ | ||||
|  | ||||
| PYTHON2 = @PYTHON2@ | ||||
| PYTHON3 = @PYTHON3@ | ||||
| PYCOMPILE = $(top_srcdir)/autoconf/py-compile | ||||
| @@ -512,9 +517,9 @@ ifeq (,$(firstword $(EXPORTED_SYMBOLS))) | ||||
| 		 ) > $@ | ||||
| else | ||||
| 	set -e;\ | ||||
| 	R=$$(sort $^ | uniq -u);\ | ||||
| 	R=$$($(SORT) $^ | uniq -u);\ | ||||
| 	test -z "$$R" || { echo "Mismatch between symbols in shared library and lists in .exported_symbols.* files: $$R"; false; } ;\ | ||||
| 	( for i in $$(echo $(EXPORTED_SYMBOLS) | tr ' ' '\n' | sort -rnt_ -k5 ); do\ | ||||
| 	( for i in $$(echo $(EXPORTED_SYMBOLS) | tr ' ' '\n' | $(SORT) -rnt_ -k5 ); do\ | ||||
| 		echo "$${i##*.} {"; echo "	global:";\ | ||||
| 		$(SED) "s/^/		/;s/$$/;/" $$i;\ | ||||
| 		echo "};";\ | ||||
|   | ||||
| @@ -23,40 +23,6 @@ dmeventd is the event monitoring daemon for device-mapper devices. | ||||
| Library plugins can register and carry out actions triggered when | ||||
| particular events occur. | ||||
| . | ||||
| .SH LVM PLUGINS | ||||
| . | ||||
| .HP | ||||
| .IR Mirror | ||||
| .br | ||||
| Attempts to handle device failure automatically. See | ||||
| .BR lvm.conf (5). | ||||
| . | ||||
| .HP | ||||
| .IR Raid | ||||
| .br | ||||
| Attempts to handle device failure automatically. See | ||||
| .BR lvm.conf (5). | ||||
| . | ||||
| .HP | ||||
| .IR Snapshot | ||||
| .br | ||||
| Monitors how full a snapshot is becoming and emits a warning to | ||||
| syslog when it exceeds 80% full. | ||||
| The warning is repeated when 85%, 90% and 95% of the snapshot is filled. | ||||
| See | ||||
| .BR lvm.conf (5). | ||||
| Snapshot which runs out of space gets invalid and when it is mounted, | ||||
| it gets umounted if possible. | ||||
| . | ||||
| .HP | ||||
| .IR Thin | ||||
| .br | ||||
| Monitors how full a thin pool data and metadata is becoming and emits | ||||
| a warning to syslog when it exceeds 80% full. | ||||
| The warning is repeated when 85%, 90% and 95% of the thin pool is filled. | ||||
| See | ||||
| .BR lvm.conf (5). | ||||
| If the thin-pool runs out of space, thin volumes are umounted if possible. | ||||
| . | ||||
| .SH OPTIONS | ||||
| . | ||||
| @@ -104,6 +70,80 @@ events to monitor from the currently running daemon. | ||||
| .br | ||||
| Show version of dmeventd. | ||||
| . | ||||
| .SH LVM PLUGINS | ||||
| . | ||||
| .HP | ||||
| .BR Mirror | ||||
| .br | ||||
| Attempts to handle device failure automatically. See | ||||
| .BR lvm.conf (5). | ||||
| . | ||||
| .HP | ||||
| .BR Raid | ||||
| .br | ||||
| Attempts to handle device failure automatically. See | ||||
| .BR lvm.conf (5). | ||||
| . | ||||
| .HP | ||||
| .BR Snapshot | ||||
| .br | ||||
| Monitors how full a snapshot is becoming and emits a warning to | ||||
| syslog when it exceeds 80% full. | ||||
| The warning is repeated when 85%, 90% and 95% of the snapshot is filled. | ||||
| See | ||||
| .BR lvm.conf (5). | ||||
| Snapshot which runs out of space gets invalid and when it is mounted, | ||||
| it gets umounted if possible. | ||||
| . | ||||
| .HP | ||||
| .BR Thin | ||||
| .br | ||||
| Monitors how full a thin pool data and metadata is becoming and emits | ||||
| a warning to syslog when it exceeds 80% full. | ||||
| The warning is repeated when more then 85%, 90% and 95% | ||||
| of the thin pool is filled. See | ||||
| .BR lvm.conf (5). | ||||
| When a thin pool fills over 50% (data or metadata) thin plugin calls | ||||
| configured \fIdmeventd/thin_command\fP with every 5% increase. | ||||
| With default setting it calls internal | ||||
| \fBlvm lvextend --use-policies\fP to resize thin pool | ||||
| when it's been filled above configured threshold | ||||
| \fIactivation/thin_pool_autoextend_threshold\fP. | ||||
| If the command fails, dmeventd thin plugin will keep | ||||
| retrying execution with increasing time delay between | ||||
| retries upto 42 minutes. | ||||
| User may also configure external command to support more advanced | ||||
| maintenance operations of a thin pool. | ||||
| Such external command can e.g. remove some unneeded snapshots, | ||||
| use \fBfstrim\fP(8) to free recover space in a thin pool, | ||||
| but also can use \fBlvextend --use-policies\fP if other actions | ||||
| have not released enough space. | ||||
| Command is executed with environmental variable | ||||
| \fBLVM_RUN_BY_DMEVENTD=1\fP so any lvm2 command executed | ||||
| in this environment will not try to interact with dmeventd. | ||||
| To see the fullness of a thin pool command may check these | ||||
| two environmental variables | ||||
| \fBDMEVENTD_THIN_POOL_DATA\fP and \fBDMEVENTD_THIN_POOL_DATA\fP. | ||||
| Command can also read status with tools like \fBlvs\fP(8). | ||||
| . | ||||
| .SH ENVIRONMENT VARIABLES | ||||
| . | ||||
| .TP | ||||
| .B DMEVENTD_THIN_POOL_DATA | ||||
| Variable is set by thin plugin and is available to executed program. Value present | ||||
| actual usage of thin pool data volume. Variable is not set when error event | ||||
| is processed. | ||||
| .TP | ||||
| .B DMEVENTD_THIN_POOL_DATA | ||||
| Variable is set by thin plugin and is available to executed program. Value present | ||||
| actual usage of thin pool metadata volume. Variable is not set when error event | ||||
| is processed. | ||||
| .TP | ||||
| .B LVM_RUN_BY_DMEVENTD | ||||
| Variable is set by thin plugin to prohibit recursive interation | ||||
| with dmeventd by any executed lvm2 command from | ||||
| a thin_command environment. | ||||
| . | ||||
| .SH SEE ALSO | ||||
| . | ||||
| .BR lvm (8), | ||||
|   | ||||
| @@ -27,9 +27,9 @@ dmsetup \(em low level logical volume management | ||||
| .  IR uuid ] | ||||
| .  RB \%[ \-\-addnodeoncreate | \-\-addnodeonresume ] | ||||
| .  RB \%[ \-n | \-\-notable | \-\-table | ||||
| .  RI \%{ table | table_file }] | ||||
| .  IR \%table | table_file ] | ||||
| .  RB [ \-\-readahead | ||||
| .  RB \%{[ + ] \fIsectors | auto | none }] | ||||
| .  RB \%[ + ] \fIsectors | auto | none ] | ||||
| .  ad b | ||||
| .. | ||||
| .CMD_CREATE | ||||
| @@ -41,7 +41,7 @@ dmsetup \(em low level logical volume management | ||||
| .  BR deps | ||||
| .  RB [ \-o | ||||
| .  IR options ] | ||||
| .  RI [ device_name ] | ||||
| .  RI [ device_name ...] | ||||
| .  ad b | ||||
| .. | ||||
| .CMD_DEPS | ||||
| @@ -58,7 +58,7 @@ dmsetup \(em low level logical volume management | ||||
| .B dmsetup | ||||
| .de CMD_INFO | ||||
| .  BR info | ||||
| .  RI [ device_name ] | ||||
| .  RI [ device_name ...] | ||||
| .. | ||||
| .CMD_INFO | ||||
| . | ||||
| @@ -92,7 +92,7 @@ dmsetup \(em low level logical volume management | ||||
| .  BR load | ||||
| .  IR device_name | ||||
| .  RB [ \-\-table | ||||
| .  RI { table | table_file }] | ||||
| .  IR table | table_file ] | ||||
| .  ad b | ||||
| .. | ||||
| .CMD_LOAD | ||||
| @@ -117,7 +117,7 @@ dmsetup \(em low level logical volume management | ||||
| .B dmsetup | ||||
| .de CMD_MANGLE | ||||
| .  BR mangle | ||||
| .  RI [ device_name ] | ||||
| .  RI [ device_name ...] | ||||
| .. | ||||
| .CMD_MANGLE | ||||
| . | ||||
| @@ -135,7 +135,7 @@ dmsetup \(em low level logical volume management | ||||
| .B dmsetup | ||||
| .de CMD_MKNODES | ||||
| .  BR mknodes | ||||
| .  RI [ device_name ] | ||||
| .  RI [ device_name ...] | ||||
| .. | ||||
| .CMD_MKNODES | ||||
| . | ||||
| @@ -146,7 +146,7 @@ dmsetup \(em low level logical volume management | ||||
| .  BR reload | ||||
| .  IR device_name | ||||
| .  RB [ \-\-table | ||||
| .  RI { table | table_file }] | ||||
| .  IR table | table_file ] | ||||
| .  ad b | ||||
| .. | ||||
| .CMD_RELOAD | ||||
| @@ -159,7 +159,7 @@ dmsetup \(em low level logical volume management | ||||
| .  RB [ \-f | \-\-force ] | ||||
| .  RB [ \-\-retry ] | ||||
| .  RB [ \-\-deferred ] | ||||
| .  IR device_name | ||||
| .  IR device_name ... | ||||
| .  ad b | ||||
| .. | ||||
| .CMD_REMOVE | ||||
| @@ -197,12 +197,12 @@ dmsetup \(em low level logical volume management | ||||
| .de CMD_RESUME | ||||
| .  ad l | ||||
| .  BR resume | ||||
| .  IR device_name | ||||
| .  IR device_name ... | ||||
| .  RB [ \-\-addnodeoncreate | \-\-addnodeonresume ] | ||||
| .  RB [ \-\-noflush ] | ||||
| .  RB [ \-\-nolockfs ] | ||||
| .  RB \%[ \-\-readahead | ||||
| .  RB \%{[ + ] \fIsectors | auto | none }] | ||||
| .  RB \%[ + ] \fIsectors | auto | none ] | ||||
| .  ad b | ||||
| .. | ||||
| .CMD_RESUME | ||||
| @@ -247,7 +247,7 @@ dmsetup \(em low level logical volume management | ||||
| .  RB [ \-\-target | ||||
| .  IR target_type ] | ||||
| .  RB [ \-\-noflush ] | ||||
| .  RI [ device_name ] | ||||
| .  RI [ device_name ...] | ||||
| .  ad b | ||||
| .. | ||||
| .CMD_STATUS | ||||
| @@ -259,7 +259,7 @@ dmsetup \(em low level logical volume management | ||||
| .  BR suspend | ||||
| .  RB [ \-\-nolockfs ] | ||||
| .  RB [ \-\-noflush ] | ||||
| .  IR device_name | ||||
| .  IR device_name ... | ||||
| .  ad b | ||||
| .. | ||||
| .CMD_SUSPEND | ||||
| @@ -272,7 +272,7 @@ dmsetup \(em low level logical volume management | ||||
| .  RB [ \-\-target | ||||
| .  IR target_type ] | ||||
| .  RB [ \-\-showkeys ] | ||||
| .  RI [ device_name ] | ||||
| .  RI [ device_name ...] | ||||
| .  ad b | ||||
| .. | ||||
| .CMD_TABLE | ||||
| @@ -354,7 +354,7 @@ dmsetup \(em low level logical volume management | ||||
| .de CMD_WIPE_TABLE | ||||
| .  ad l | ||||
| .  BR wipe_table | ||||
| .  IR device_name | ||||
| .  IR device_name ... | ||||
| .  RB [ \-f | \-\-force ] | ||||
| .  RB [ \-\-noflush ] | ||||
| .  RB [ \-\-nolockfs ] | ||||
| @@ -447,7 +447,7 @@ The default interval is one second. | ||||
| . | ||||
| .HP | ||||
| .BR \-\-manglename | ||||
| .RB { auto | hex | none } | ||||
| .BR auto | hex | none | ||||
| .br | ||||
| Mangle any character not on a whitelist using mangling_mode when | ||||
| processing device-mapper device names and UUIDs. The names and UUIDs | ||||
| @@ -529,7 +529,7 @@ Specify which fields to display. | ||||
| . | ||||
| .HP | ||||
| .BR \-\-readahead | ||||
| .RB {[ + ] \fIsectors | auto | none } | ||||
| .RB [ + ] \fIsectors | auto | none | ||||
| .br | ||||
| Specify read ahead size in units of sectors. | ||||
| The default value is \fBauto\fP which allows the kernel to choose | ||||
|   | ||||
| @@ -44,7 +44,7 @@ dmstats \(em device-mapper statistics management | ||||
| .B dmsetup | ||||
| .B stats | ||||
| .I command | ||||
| .RB [ options ] | ||||
| [OPTIONS] | ||||
| .sp | ||||
| . | ||||
| .PD 0 | ||||
| @@ -53,13 +53,13 @@ dmstats \(em device-mapper statistics management | ||||
| .de CMD_COMMAND | ||||
| .  ad l | ||||
| .  IR command | ||||
| .  RI [ device_name | | ||||
| .  RB [ \-u | \-\-uuid | ||||
| .  IR uuid ] | ||||
| .  RB | [ \-\-major | ||||
| .  IR device_name " |" | ||||
| .  BR \-\-major | ||||
| .  IR major | ||||
| .  BR \-\-minor | ||||
| .  IR minor ] | ||||
| .  IR minor " |" | ||||
| .  BR \-u | \-\-uuid | ||||
| .  IR uuid | ||||
| .  RB \%[ \-v | \-\-verbose] | ||||
| .  ad b | ||||
| .. | ||||
| @@ -82,9 +82,7 @@ dmstats \(em device-mapper statistics management | ||||
| .de CMD_CREATE | ||||
| .  ad l | ||||
| .  BR create | ||||
| .  RB [ device_name... | ||||
| .  RB | file_path... | ||||
| .  RB | [ \-\-alldevices ]] | ||||
| .  IR device_name... | file_path... | \fB\-\-alldevices | ||||
| .  RB [ \-\-areas | ||||
| .  IR nr_areas | \fB\-\-areasize | ||||
| .  IR area_size ] | ||||
| @@ -110,8 +108,7 @@ dmstats \(em device-mapper statistics management | ||||
| .de CMD_DELETE | ||||
| .  ad l | ||||
| .  BR delete | ||||
| .  RI [ device_name ] | ||||
| .  RB [ \-\-alldevices ] | ||||
| .  IR device_name | \fB\-\-alldevices | ||||
| .  OPT_PROGRAMS | ||||
| .  OPT_REGIONS | ||||
| .  ad b | ||||
| @@ -123,10 +120,9 @@ dmstats \(em device-mapper statistics management | ||||
| .de CMD_GROUP | ||||
| .  ad l | ||||
| .  BR group | ||||
| .  RI [ device_name ] | ||||
| .  RI [ device_name | \fB\-\-alldevices ] | ||||
| .  RB [ \-\-alias | ||||
| .  IR name ] | ||||
| .  RB [ \-\-alldevices ] | ||||
| .  RB [ \-\-regions | ||||
| .  IR regions ] | ||||
| .  ad b | ||||
| @@ -205,8 +201,7 @@ dmstats \(em device-mapper statistics management | ||||
| .de CMD_UNGROUP | ||||
| .  ad l | ||||
| .  BR ungroup | ||||
| .  RI [ device_name ] | ||||
| .  RB [ \-\-alldevices ] | ||||
| .  RI [ device_name | \fB\-\-alldevices ] | ||||
| .  RB [ \-\-groupid | ||||
| .  IR id ] | ||||
| .  ad b | ||||
| @@ -217,7 +212,7 @@ dmstats \(em device-mapper statistics management | ||||
| .de CMD_UPDATE_FILEMAP | ||||
| .  ad l | ||||
| .  BR update_filemap | ||||
| .  RI file_path | ||||
| .  IR file_path | ||||
| .  RB [ \-\-groupid | ||||
| .  IR id ] | ||||
| .  ad b | ||||
|   | ||||
| @@ -20,12 +20,6 @@ type is deprecated and the | ||||
| .B raid1 | ||||
| type should be used.  They are both implementations of mirroring. | ||||
|  | ||||
| The | ||||
| .B raid* | ||||
| type refers to one of many raid levels, e.g. | ||||
| .B raid1, | ||||
| .B raid5. | ||||
|  | ||||
| In some cases, an LV is a single device mapper (dm) layer above physical | ||||
| devices.  In other cases, hidden LVs (dm devices) are layered between the | ||||
| visible LV and physical devices.  LVs in the middle layers are called sub LVs. | ||||
|   | ||||
| @@ -1,3 +1,24 @@ | ||||
| .SH NOTES | ||||
|  | ||||
| This previous command syntax would perform two different operations: | ||||
| .br | ||||
| \fBlvconvert --thinpool\fP \fILV1\fP \fB--poolmetadata\fP \fILV2\fP | ||||
| .br | ||||
| If LV1 was not a thin pool, the command would convert LV1 to | ||||
| a thin pool, optionally using a specified LV for metadata. | ||||
| But, if LV1 was already a thin pool, the command would swap | ||||
| the current metadata LV with LV2 (for repair purposes.) | ||||
|  | ||||
| In the same way, this previous command syntax would perform two different | ||||
| operations: | ||||
| .br | ||||
| \fBlvconvert --cachepool\fP \fILV1\fP \fB--poolmetadata\fP \fILV2\fP | ||||
| .br | ||||
| If LV1 was not a cache pool, the command would convert LV1 to | ||||
| a cache pool, optionally using a specified LV for metadata. | ||||
| But, if LV1 was already a cache pool, the command would swap | ||||
| the current metadata LV with LV2 (for repair purposes.) | ||||
|  | ||||
| .SH EXAMPLES | ||||
|  | ||||
| Convert a linear LV to a two-way mirror LV. | ||||
|   | ||||
| @@ -26,3 +26,14 @@ virtual size rather than a physical size. A cache LV is the combination of | ||||
| a standard LV with a cache pool, used to cache active portions of the LV | ||||
| to improve performance. | ||||
|  | ||||
| .SS Usage notes | ||||
|  | ||||
| In the usage section below, \fB--size\fP \fINumber\fP can be replaced | ||||
| in each case with \fB--extents\fP \fINumberExtents\fP.  Also see both | ||||
| descriptions the options section. | ||||
|  | ||||
| In the usage section below, \fB--name\fP is omitted from the required | ||||
| options, even though it is typically used.  When the name is not | ||||
| specified, a new LV name is generated with the "lvol" prefix and a unique | ||||
| numeric suffix.  Also see the description in the options section. | ||||
|  | ||||
|   | ||||
							
								
								
									
										5
									
								
								man/lvm-config.8.des
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								man/lvm-config.8.des
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| This command is the same as \fBlvmconfig\fP(8). | ||||
|  | ||||
| lvm config produces formatted output from the LVM configuration tree. The | ||||
| sources of the configuration data include \fBlvm.conf\fP(5) and command | ||||
| line settings from \-\-config. | ||||
							
								
								
									
										5
									
								
								man/lvm-dumpconfig.8.des
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								man/lvm-dumpconfig.8.des
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| This command is the same as \fBlvmconfig\fP(8). | ||||
|  | ||||
| lvm dumpconfig produces formatted output from the LVM configuration tree. The | ||||
| sources of the configuration data include \fBlvm.conf\fP(5) and command | ||||
| line settings from \-\-config. | ||||
							
								
								
									
										108
									
								
								man/lvm.8.in
									
									
									
									
									
								
							
							
						
						
									
										108
									
								
								man/lvm.8.in
									
									
									
									
									
								
							| @@ -484,48 +484,70 @@ directly. | ||||
| .SH SEE ALSO | ||||
| . | ||||
| .nh | ||||
| .BR lvm.conf (5), | ||||
| .BR lvmcache (7), | ||||
| .BR lvmreport(7), | ||||
| .BR lvmthin (7), | ||||
| .BR clvmd (8), | ||||
| .BR lvm (8) | ||||
| .BR lvm.conf (5) | ||||
| .BR lvmconfig (8) | ||||
|  | ||||
| .BR pvchange (8) | ||||
| .BR pvck (8) | ||||
| .BR pvcreate (8) | ||||
| .BR pvdisplay (8) | ||||
| .BR pvmove (8) | ||||
| .BR pvremove (8) | ||||
| .BR pvresize (8) | ||||
| .BR pvs (8) | ||||
| .BR pvscan (8)  | ||||
|  | ||||
| .BR vgcfgbackup (8) | ||||
| .BR vgcfgrestore (8) | ||||
| .BR vgchange (8) | ||||
| .BR vgck (8) | ||||
| .BR vgcreate (8) | ||||
| .BR vgconvert (8) | ||||
| .BR vgdisplay (8) | ||||
| .BR vgexport (8) | ||||
| .BR vgextend (8) | ||||
| .BR vgimport (8) | ||||
| .BR vgimportclone (8) | ||||
| .BR vgmerge (8) | ||||
| .BR vgmknodes (8) | ||||
| .BR vgreduce (8) | ||||
| .BR vgremove (8) | ||||
| .BR vgrename (8) | ||||
| .BR vgs (8) | ||||
| .BR vgscan (8) | ||||
| .BR vgsplit (8)  | ||||
|  | ||||
| .BR lvcreate (8) | ||||
| .BR lvchange (8) | ||||
| .BR lvconvert (8) | ||||
| .BR lvdisplay (8) | ||||
| .BR lvextend (8) | ||||
| .BR lvreduce (8) | ||||
| .BR lvremove (8) | ||||
| .BR lvrename (8) | ||||
| .BR lvresize (8) | ||||
| .BR lvs (8) | ||||
| .BR lvscan (8) | ||||
|  | ||||
| .BR lvm2-activation-generator (8) | ||||
| .BR blkdeactivate (8) | ||||
| .BR lvmdump (8) | ||||
|  | ||||
| .BR dmeventd (8) | ||||
| .BR lvmetad (8) | ||||
| .BR lvmpolld (8) | ||||
| .BR lvmlockd (8) | ||||
| .BR lvmlockctl (8) | ||||
| .BR clvmd (8) | ||||
| .BR cmirrord (8) | ||||
| .BR lvmdbusd (8) | ||||
|  | ||||
| .BR lvmsystemid (7) | ||||
| .BR lvmreport (7) | ||||
| .BR lvmraid (7) | ||||
| .BR lvmthin (7) | ||||
| .BR lvmcache (7) | ||||
|  | ||||
| .BR dmsetup (8), | ||||
| .BR lvchange (8), | ||||
| .BR lvcreate (8), | ||||
| .BR lvdisplay (8), | ||||
| .BR lvextend (8), | ||||
| .BR lvmchange (8), | ||||
| .BR lvmconfig (8), | ||||
| .BR lvmdiskscan (8), | ||||
| .BR lvreduce (8), | ||||
| .BR lvremove (8), | ||||
| .BR lvrename (8), | ||||
| .BR lvresize (8), | ||||
| .BR lvs (8), | ||||
| .BR lvscan (8), | ||||
| .BR pvchange (8), | ||||
| .BR pvck (8), | ||||
| .BR pvcreate (8), | ||||
| .BR pvdisplay (8), | ||||
| .BR pvmove (8), | ||||
| .BR pvremove (8), | ||||
| .BR pvs (8), | ||||
| .BR pvscan (8), | ||||
| .BR vgcfgbackup (8), | ||||
| .BR vgchange  (8), | ||||
| .BR vgck (8), | ||||
| .BR vgconvert (8), | ||||
| .BR vgcreate (8), | ||||
| .BR vgdisplay (8), | ||||
| .BR vgextend (8), | ||||
| .BR vgimport (8), | ||||
| .BR vgimportclone (8), | ||||
| .BR vgmerge (8), | ||||
| .BR vgmknodes (8), | ||||
| .BR vgreduce (8), | ||||
| .BR vgremove (8), | ||||
| .BR vgrename (8), | ||||
| .BR vgs (8), | ||||
| .BR vgscan (8), | ||||
| .BR vgsplit (8), | ||||
| .BR readline (3) | ||||
|   | ||||
| @@ -278,22 +278,6 @@ or vgchange to activate thin snapshots with the "k" attribute. | ||||
|  | ||||
| \& | ||||
|  | ||||
| .SS Alternate syntax for specifying type thin\-pool | ||||
|  | ||||
| \& | ||||
|  | ||||
| The fully specified syntax for creating a thin pool LV shown above is: | ||||
|  | ||||
| .B lvconvert \-\-type thin-pool \-\-poolmetadata VG/ThinMetaLV VG/ThinDataLV | ||||
|  | ||||
| An alternate syntax may be used for the same operation: | ||||
|  | ||||
| .B lvconvert \-\-thinpool VG/ThinDataLV \-\-poolmetadata VG/ThinMetaLV | ||||
|  | ||||
| The thin-pool type is inferred by lvm; the \-\-thinpool option is not an | ||||
| alias for \-\-type thin\-pool. | ||||
|  | ||||
|  | ||||
| .SS Automatic pool metadata LV | ||||
|  | ||||
| \& | ||||
|   | ||||
| @@ -6,6 +6,11 @@ removal.  LVs cannot be deactivated or removed while they are open (e.g. | ||||
| if they contain a mounted filesystem). Removing an origin LV will also | ||||
| remove all dependent snapshots. | ||||
|  | ||||
| When a single force option is used, LVs are removed without confirmation, | ||||
| and the command will try to deactivate unused LVs. | ||||
|  | ||||
| To remove damaged LVs, two force options may be required (\fB-ff\fP). | ||||
|  | ||||
| \fBHistorical LVs\fP | ||||
|  | ||||
| If the configuration setting \fBmetadata/record_lvs_history\fP is enabled | ||||
|   | ||||
| @@ -16,3 +16,6 @@ data on that disk. This can be done by zeroing the first sector with: | ||||
| Use \fBvgcreate\fP(8) to create a new VG on the PV, or \fBvgextend\fP(8) | ||||
| to add the PV to existing VG. | ||||
|  | ||||
| The force option will create a PV without confirmation.  Repeating the | ||||
| force option (\fB-ff\fP) will forcibly create a PV, overriding checks that | ||||
| normally prevent it, e.g. if the PV is already in a VG. | ||||
|   | ||||
| @@ -14,48 +14,3 @@ More than one pvmove can run concurrently if they are moving data from | ||||
| different source PVs, but additional pvmoves will ignore any LVs already | ||||
| in the process of being changed, so some data might not get moved. | ||||
|  | ||||
| pvmove works as follows: | ||||
|  | ||||
| 1. A temporary 'pvmove' LV is created to store details of all the data | ||||
| movements required. | ||||
|  | ||||
| 2. Every LV in the VG is searched for contiguous data that need moving | ||||
| according to the command line arguments. | ||||
| For each piece of data found, a new segment is added to the end of the | ||||
| pvmove LV. | ||||
| This segment takes the form of a temporary mirror to copy the data  | ||||
| from the original location to a newly allocated location. | ||||
| The original LV is updated to use the new temporary mirror segment | ||||
| in the pvmove LV instead of accessing the data directly. | ||||
|  | ||||
| 3. The VG metadata is updated on disk. | ||||
|  | ||||
| 4. The first segment of the pvmove LV is activated and starts to mirror | ||||
| the first part of the data.  Only one segment is mirrored at once as this | ||||
| is usually more efficient. | ||||
|  | ||||
| 5. A daemon repeatedly checks progress at the specified time interval. | ||||
| When it detects that the first temporary mirror is in sync, it breaks that | ||||
| mirror so that only the new location for that data gets used and writes a | ||||
| checkpoint into the VG metadata on disk.  Then it activates the mirror for | ||||
| the next segment of the pvmove LV. | ||||
|  | ||||
| 6. When there are no more segments left to be mirrored, the temporary LV | ||||
| is removed and the VG metadata is updated so that the LVs reflect the new | ||||
| data locations. | ||||
|  | ||||
| Note that this new process cannot support the original LVM1 | ||||
| type of on-disk metadata.  Metadata can be converted using | ||||
| \fBvgconvert\fP(8). | ||||
|  | ||||
| If the \fB\-\-atomic\fP option is used, a slightly different approach is | ||||
| used for the move.  Again, a temporary 'pvmove' LV is created to store the | ||||
| details of all the data movements required.  This temporary LV contains | ||||
| all the segments of the various LVs that need to be moved.  However, in | ||||
| this case, an identical LV is allocated that contains the same number of | ||||
| segments and a mirror is created to copy the contents from the first | ||||
| temporary LV to the second.  After a complete copy is made, the temporary | ||||
| LVs are removed, leaving behind the segments on the destination PV.  If an | ||||
| abort is issued during the move, all LVs being moved will remain on the | ||||
| source PV. | ||||
|  | ||||
|   | ||||
| @@ -1,3 +1,50 @@ | ||||
| .SH NOTES | ||||
|  | ||||
| pvmove works as follows: | ||||
|  | ||||
| 1. A temporary 'pvmove' LV is created to store details of all the data | ||||
| movements required. | ||||
|  | ||||
| 2. Every LV in the VG is searched for contiguous data that need moving | ||||
| according to the command line arguments. | ||||
| For each piece of data found, a new segment is added to the end of the | ||||
| pvmove LV. | ||||
| This segment takes the form of a temporary mirror to copy the data | ||||
| from the original location to a newly allocated location. | ||||
| The original LV is updated to use the new temporary mirror segment | ||||
| in the pvmove LV instead of accessing the data directly. | ||||
|  | ||||
| 3. The VG metadata is updated on disk. | ||||
|  | ||||
| 4. The first segment of the pvmove LV is activated and starts to mirror | ||||
| the first part of the data.  Only one segment is mirrored at once as this | ||||
| is usually more efficient. | ||||
|  | ||||
| 5. A daemon repeatedly checks progress at the specified time interval. | ||||
| When it detects that the first temporary mirror is in sync, it breaks that | ||||
| mirror so that only the new location for that data gets used and writes a | ||||
| checkpoint into the VG metadata on disk.  Then it activates the mirror for | ||||
| the next segment of the pvmove LV. | ||||
|  | ||||
| 6. When there are no more segments left to be mirrored, the temporary LV | ||||
| is removed and the VG metadata is updated so that the LVs reflect the new | ||||
| data locations. | ||||
|  | ||||
| Note that this new process cannot support the original LVM1 | ||||
| type of on-disk metadata.  Metadata can be converted using | ||||
| \fBvgconvert\fP(8). | ||||
|  | ||||
| If the \fB\-\-atomic\fP option is used, a slightly different approach is | ||||
| used for the move.  Again, a temporary 'pvmove' LV is created to store the | ||||
| details of all the data movements required.  This temporary LV contains | ||||
| all the segments of the various LVs that need to be moved.  However, in | ||||
| this case, an identical LV is allocated that contains the same number of | ||||
| segments and a mirror is created to copy the contents from the first | ||||
| temporary LV to the second.  After a complete copy is made, the temporary | ||||
| LVs are removed, leaving behind the segments on the destination PV.  If an | ||||
| abort is issued during the move, all LVs being moved will remain on the | ||||
| source PV. | ||||
|  | ||||
| .SH EXAMPLES | ||||
|  | ||||
| Move all physical extents that are used by simple LVs on the specified PV to | ||||
|   | ||||
| @@ -1,2 +1,7 @@ | ||||
| pvremove wipes the label on a device so that LVM will no longer recognise | ||||
| it as a PV. | ||||
|  | ||||
| A PV cannot be removed from a VG while it is used by an active LV. | ||||
|  | ||||
| Repeat the force option (\fB-ff\fP) to forcibly remove a PV belonging to | ||||
| an existing VG. Normally, \fBvgreduce\fP(8) should be used instead. | ||||
|   | ||||
| @@ -6,3 +6,6 @@ A back up file can be specified with \fB\-\-file\fP.  If no backup file is | ||||
| specified, the most recent one is used. Use \fB\-\-list\fP for a list of | ||||
| the available back up and archive files of a VG. | ||||
|  | ||||
| WARNING: When a VG contains thin pools, changes to thin metadata cannot be | ||||
| reverted, and data loss may occur if thin metadata has changed. The force | ||||
| option is required to restore in this case. | ||||
|   | ||||
| @@ -4,3 +4,6 @@ to confirm LV removal. | ||||
| If one or more PVs in the VG are lost, consider | ||||
| \fBvgreduce \-\-removemissing\fP to make the VG | ||||
| metadata consistent again. | ||||
|  | ||||
| Repeat the force option (\fB-ff\fP) to forcibly remove LVs in the VG | ||||
| without confirmation. | ||||
|   | ||||
| @@ -39,7 +39,7 @@ S ?= @ # never match anything by default | ||||
| VERBOSE ?= 0 | ||||
| ALL := $(shell find -L $(srcdir) \( -path \*/shell/\*.sh -or -path \*/api/\*.sh \) | sort) | ||||
| comma = , | ||||
| RUN := $(shell find -L $(srcdir) -regextype posix-egrep \( -path \*/shell/\*.sh -or -path \*/api/\*.sh \) -and -regex "$(srcdir)/.*($(subst $(comma),|,$(T))).*" -and -not -regex "$(srcdir)/.*($(subst $(comma),|,$(S))).*" | sort) | ||||
| RUN := $(shell find -L $(srcdir) -regextype posix-egrep \( -path \*/shell/\*.sh -or -path \*/api/\*.sh \) -and -regex "$(srcdir)/.*($(subst $(comma),|,$(T))).*" -and -not -regex "$(srcdir)/.*($(subst $(comma),|,$(S))).*" | ($SORT)) | ||||
| RUN_BASE = $(subst $(srcdir)/,,$(RUN)) | ||||
|  | ||||
| ifeq ("@BUILD_LVMETAD@", "yes") | ||||
| @@ -267,7 +267,7 @@ lib/%: lib/%.o .lib-dir-stamp | ||||
|  | ||||
| lib/%: $(srcdir)/lib/%.sh .lib-dir-stamp | ||||
| 	cp $< $@ | ||||
| 	chmod +x $@ | ||||
| 	$(CHMOD) +x $@ | ||||
|  | ||||
| lib/flavour-%: $(srcdir)/lib/flavour-%.sh .lib-dir-stamp | ||||
| 	cp $< $@ | ||||
|   | ||||
| @@ -405,23 +405,28 @@ teardown_devs_prefixed() { | ||||
| 	fi | ||||
|  | ||||
| 	# Remove devices, start with closed (sorted by open count) | ||||
| 	local remfail=no | ||||
| 	# Run 'dmsetup remove' in parallel | ||||
| 	local need_udev_wait=0 | ||||
| 	rm -f REMOVE_FAILED | ||||
| 	#local listdevs=( $(dm_info name,open --sort open,name | grep "$prefix.*:0") ) | ||||
| 	#dmsetup remove --deferred ${listdevs[@]%%:0} || touch REMOVE_FAILED | ||||
|  | ||||
| 	init_udev_transaction | ||||
| 	for dm in $(dm_info name --sort open | grep "$prefix"); do | ||||
| 		dmsetup remove "$dm" &>/dev/null || remfail=yes | ||||
| 	for dm in $(dm_info name --sort open,name | grep "$prefix"); do | ||||
| 		dmsetup remove "$dm" &>/dev/null || touch REMOVE_FAILED & | ||||
| 		need_udev_wait=1 | ||||
| 	done | ||||
| 	wait | ||||
| 	finish_udev_transaction | ||||
| 	test $need_udev_wait -eq 0 || udev_wait | ||||
|  | ||||
| 	if test $remfail = yes; then | ||||
| 	if test -f REMOVE_FAILED; then | ||||
| 		local num_devs | ||||
| 		local num_remaining_devs=999 | ||||
| 		while num_devs=$(dm_table | grep "$prefix" | wc -l) && \ | ||||
| 		    test $num_devs -lt $num_remaining_devs -a $num_devs -ne 0; do | ||||
| 			test "$stray" -eq 0 || echo "Removing $num_devs stray mapped devices with names beginning with $prefix: " | ||||
|                         # HACK: sort also by minors - so we try to close 'possibly later' created device first | ||||
| 			# HACK: sort also by minors - so we try to close 'possibly later' created device first | ||||
| 			for dm in $(dm_info name --sort open,-minor | grep "$prefix") ; do | ||||
| 				dmsetup remove -f "$dm" || true | ||||
| 			done | ||||
| @@ -794,6 +799,7 @@ prepare_devs() { | ||||
|  | ||||
| 	local size=$(($devsize*2048)) # sectors | ||||
| 	local count=0 | ||||
| 	rm -f CREATE_FAILED | ||||
| 	init_udev_transaction | ||||
| 	for i in $(seq 1 $n); do | ||||
| 		local name="${PREFIX}$pvname$i" | ||||
| @@ -801,17 +807,19 @@ prepare_devs() { | ||||
| 		DEVICES[$count]=$dev | ||||
| 		count=$(( $count + 1 )) | ||||
| 		echo 0 $size linear "$BACKING_DEV" $((($i-1)*$size + $shift)) > "$name.table" | ||||
| 		if not dmsetup create -u "TEST-$name" "$name" "$name.table" && | ||||
| 		   test -n "$LVM_TEST_BACKING_DEVICE"; | ||||
| 		then # maybe the backing device is too small for this test | ||||
| 		    LVM_TEST_BACKING_DEVICE= | ||||
| 		    rm -f BACKING_DEV | ||||
| 		    prepare_devs "$@" | ||||
| 		    return $? | ||||
| 		fi | ||||
| 		dmsetup create -u "TEST-$name" "$name" "$name.table" || touch CREATE_FAILED & | ||||
| 		test -f CREATE_FAILED && break; | ||||
| 	done | ||||
| 	wait | ||||
| 	finish_udev_transaction | ||||
|  | ||||
| 	if test -f CREATE_FAILED -a -n "$LVM_TEST_BACKING_DEVICE"; then | ||||
| 		LVM_TEST_BACKING_DEVICE= | ||||
| 		rm -f BACKING_DEV CREATE_FAILED | ||||
| 		prepare_devs "$@" | ||||
| 		return $? | ||||
| 	fi | ||||
|  | ||||
| 	# non-ephemeral devices need to be cleared between tests | ||||
| 	test -f LOOP || for d in ${DEVICES[@]}; do | ||||
| 		blkdiscard "$d" 2>/dev/null || true | ||||
| @@ -833,9 +841,11 @@ prepare_devs() { | ||||
| #	( IFS=$'\n'; echo "${DEVICES[*]}" ) >DEVICES | ||||
| 	echo "ok" | ||||
|  | ||||
| 	for dev in "${DEVICES[@]}"; do | ||||
| 		notify_lvmetad "$dev" | ||||
| 	done | ||||
| 	if test -e LOCAL_LVMETAD; then | ||||
| 		for dev in "${DEVICES[@]}"; do | ||||
| 			notify_lvmetad "$dev" | ||||
| 		done | ||||
| 	fi | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -856,7 +866,7 @@ common_dev_() { | ||||
| 		else | ||||
| 			test -z "${offsets[@]}" && offsets="0:" | ||||
| 		fi ;; | ||||
| 	error)  offsets=${@:3} | ||||
| 	error|zero)  offsets=${@:3} | ||||
| 		test -z "${offsets[@]}" && offsets="0:" ;; | ||||
| 	esac | ||||
|  | ||||
| @@ -883,8 +893,8 @@ common_dev_() { | ||||
| 		case "$tgtype" in | ||||
| 		delay) | ||||
| 			echo "$from $len delay $pvdev $(($pos + $offset)) $read_ms $pvdev $(($pos + $offset)) $write_ms" ;; | ||||
| 		error) | ||||
| 			echo "$from $len error" ;; | ||||
| 		error|zero) | ||||
| 			echo "$from $len $tgtype" ;; | ||||
| 		esac | ||||
| 		pos=$(($pos + $len)) | ||||
| 	done > "$name.devtable" | ||||
| @@ -1003,12 +1013,23 @@ restore_from_devtable() { | ||||
| # | ||||
| # Convert device to device with errors | ||||
| # Takes the list of pairs of error segment from:len | ||||
| # Original device table is replace with multiple lines | ||||
| # Combination with zero or delay is unsupported | ||||
| # Original device table is replaced with multiple lines | ||||
| # i.e.  error_dev "$dev1" 8:32 96:8 | ||||
| error_dev() { | ||||
| 	common_dev_ error "$@" | ||||
| } | ||||
|  | ||||
| # | ||||
| # Convert existing device to a device with zero segments | ||||
| # Takes the list of pairs of zero segment from:len | ||||
| # Combination with error or delay is unsupported | ||||
| # Original device table is replaced with multiple lines | ||||
| # i.e.  zero_dev "$dev1" 8:32 96:8 | ||||
| zero_dev() { | ||||
| 	common_dev_ zero "$@" | ||||
| } | ||||
|  | ||||
| backup_dev() { | ||||
| 	local dev | ||||
|  | ||||
|   | ||||
| @@ -77,6 +77,11 @@ find "$TESTOLDPWD/lib" ! \( -name '*.sh' -o -name '*.[cdo]' \ | ||||
| DM_DEFAULT_NAME_MANGLING_MODE=none | ||||
| DM_DEV_DIR="$TESTDIR/dev" | ||||
| LVM_SYSTEM_DIR="$TESTDIR/etc" | ||||
| # abort on the internal dm errors in the tests (allowing test user override) | ||||
| DM_ABORT_ON_INTERNAL_ERRORS=${DM_ABORT_ON_INTERNAL_ERRORS:-1} | ||||
|  | ||||
| export DM_DEFAULT_NAME_MANGLING_MODE DM_DEV_DIR LVM_SYSTEM_DIR DM_ABORT_ON_INTERNAL_ERRORS | ||||
|  | ||||
| mkdir "$LVM_SYSTEM_DIR" "$DM_DEV_DIR" | ||||
| if test -n "$LVM_TEST_DEVDIR" ; then | ||||
| 	test -d "$LVM_TEST_DEVDIR" || die "Test device directory LVM_TEST_DEVDIR=\"$LVM_TEST_DEVDIR\" is not valid." | ||||
| @@ -85,14 +90,11 @@ else | ||||
| 	mknod "$DM_DEV_DIR/testnull" c 1 3 || die "mknod failed" | ||||
| 	echo >"$DM_DEV_DIR/testnull" || \ | ||||
| 		die "Filesystem does support devices in $DM_DEV_DIR (mounted with nodev?)" | ||||
| 	mkdir "$DM_DEV_DIR/mapper" | ||||
| 	# dmsetup makes here needed control entry if still missing | ||||
| 	dmsetup version || \ | ||||
| 		die "Dmsetup in $DM_DEV_DIR can't report version?" | ||||
| fi | ||||
|  | ||||
| # abort on the internal dm errors in the tests (allowing test user override) | ||||
| DM_ABORT_ON_INTERNAL_ERRORS=${DM_ABORT_ON_INTERNAL_ERRORS:-1} | ||||
|  | ||||
| export DM_DEFAULT_NAME_MANGLING_MODE DM_DEV_DIR LVM_SYSTEM_DIR DM_ABORT_ON_INTERNAL_ERRORS | ||||
|  | ||||
| echo "$TESTNAME" >TESTNAME | ||||
|  | ||||
| echo "Kernel is $(uname -a)" | ||||
|   | ||||
							
								
								
									
										41
									
								
								test/shell/lvchange-raid1-writemostly.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								test/shell/lvchange-raid1-writemostly.sh
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| #!/bin/sh | ||||
| # Copyright (C) 2017 Red Hat, Inc. All rights reserved. | ||||
| # | ||||
| # 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 General Public License v.2. | ||||
| # | ||||
| # You should have received a copy of the GNU General Public License | ||||
| # along with this program; if not, write to the Free Software Foundation, | ||||
| # Inc., 51 Franklin Street, Fifth Floor, Boston, MA2110-1301 USA | ||||
|  | ||||
| SKIP_WITH_LVMLOCKD=1 | ||||
| SKIP_WITH_LVMPOLLD=1 | ||||
|  | ||||
| . lib/inittest | ||||
|  | ||||
| which mkfs.ext4 || skip | ||||
| aux have_raid 1 3 5 || skip | ||||
|  | ||||
| aux prepare_vg 4 | ||||
|  | ||||
| for d in $dev1 $dev2 $dev3 $dev4 | ||||
| do | ||||
| 	aux delay_dev $d 1 | ||||
| done | ||||
|  | ||||
| # | ||||
| # Test writemostly prohibited on resyncrhonizing raid1 | ||||
| # | ||||
|  | ||||
| # Create 4-way striped LV | ||||
| lvcreate -aey --ty raid1 -m 3 -L 32M -n $lv1 $vg | ||||
| not lvchange -y --writemostly $dev1 $vg/$lv1 | ||||
| check lv_field $vg/$lv1 segtype "raid1" | ||||
| check lv_field $vg/$lv1 stripes 4 | ||||
| check lv_attr_bit health $vg/${lv1}_rimage_0 "-" | ||||
| aux wait_for_sync $vg $lv1 | ||||
| lvchange -y --writemostly $dev1 $vg/$lv1 | ||||
| check lv_attr_bit health $vg/${lv1}_rimage_0 "w" | ||||
|  | ||||
| vgremove -ff $vg | ||||
| @@ -28,7 +28,7 @@ grep "$dev1" out | ||||
| # check for RHBZ 1080189 -- SEGV in lvremove/vgremove | ||||
| pvcreate -ff -y --metadatatype 1 "$dev1" "$dev2" | ||||
| vgcreate --metadatatype 1 $vg1 "$dev1" "$dev2" | ||||
| lvcreate -l1 $vg1 | ||||
| lvcreate -l1 $vg1 "$dev1" | ||||
| pvremove -ff -y "$dev2" | ||||
| vgchange -an $vg1 | ||||
| not lvremove $vg1 | ||||
|   | ||||
| @@ -34,9 +34,26 @@ lvremove -ff $vg | ||||
|  | ||||
| lvcreate -L 10M -n lv $vg "$dev1" | ||||
| lvextend -L +10M $vg/lv "$dev2" | ||||
| lvextend --type striped -m0 -L +10M $vg/lv "$dev2" | ||||
|  | ||||
| # Attempt to reduce with lvextend and vice versa: | ||||
| not lvextend -L 16M $vg/lv | ||||
| not lvreduce -L 32M $vg/lv | ||||
|  | ||||
| lvremove -ff $vg | ||||
|  | ||||
| lvcreate --type mirror -aey -L 4 -n $lv1 $vg | ||||
| # Incorrent name for resized LV | ||||
| not lvextend --type mirror -L 10 -n $lv1 $vg | ||||
| # Same size | ||||
| not lvextend --type mirror -L 4 $vg/$lv1 | ||||
| # Cannot use any '-' or '+'  sign for --mirror arg | ||||
| not lvextend --type mirror -L+2 -m-1 $vg/$lv1 | ||||
| not lvextend --type mirror -L+2 -m+1 $vg/$lv1 | ||||
|  | ||||
| lvextend --type mirror -L+4 -m1 $vg/$lv1 | ||||
|  | ||||
| lvs -a $vg | ||||
| check  lv_field $vg/$lv1 size "8.00m" | ||||
|  | ||||
| lvremove -ff $vg | ||||
|   | ||||
| @@ -33,9 +33,9 @@ test_pvmove_resume() { | ||||
| 	# next LV on same VG and differetnt PV (we want to test 2 pvmoves per VG) | ||||
| 	lvcreate -an -Zn -l30 -n $lv2 $vg "$dev3" | ||||
|  | ||||
| 	aux delay_dev "$dev4" 0 250 | ||||
| 	aux delay_dev "$dev4" 0 250 $(get first_extent_sector "$dev4"): | ||||
| 	test -e HAVE_DM_DELAY || { lvremove -f $vg; return 0; } | ||||
| 	aux delay_dev "$dev5" 0 250 | ||||
| 	aux delay_dev "$dev5" 0 250 $(get first_extent_sector "$dev5"): | ||||
|  | ||||
| 	pvmove -i5 "$dev1" "$dev4" & | ||||
| 	PVMOVE=$! | ||||
|   | ||||
| @@ -173,14 +173,7 @@ liblvm2cmd.$(LIB_SUFFIX).$(LIB_VERSION): liblvm2cmd.$(LIB_SUFFIX) | ||||
|  | ||||
| .commands: $(srcdir)/commands.h $(srcdir)/cmdnames.h Makefile | ||||
| 	$(CC) -E -P $(srcdir)/cmdnames.h 2> /dev/null | \ | ||||
| 		egrep -v '^ *(|#.*|config|devtypes|dumpconfig|formats|fullreport|help|lastlog|lvpoll|pvdata|segtypes|systemid|tags|version) *$$' > .commands | ||||
|  | ||||
| .DELETE_ON_ERROR: | ||||
|  | ||||
| # move properly to configure | ||||
| WC = /usr/bin/wc | ||||
| GREP = /bin/grep | ||||
| SORT = /bin/sort | ||||
| 		$(EGREP) -v '^ *(|#.*|config|devtypes|dumpconfig|formats|fullreport|help|lastlog|lvpoll|pvdata|segtypes|systemid|tags|version) *$$' > .commands | ||||
|  | ||||
| command-count.h: $(srcdir)/command-lines.in Makefile | ||||
| 	set -o pipefail && \ | ||||
| @@ -204,11 +197,12 @@ command-lines-input.h: $(srcdir)/command-lines.in Makefile | ||||
| 	( cat $(top_srcdir)/doc/license.txt && \ | ||||
| 	  echo "/* Do not edit. This file is generated by the Makefile. */" && \ | ||||
| 	  echo -en "const char _command_input[] =\n\n\"" && \ | ||||
| 	  $(GREP) -Ev '^#|\-\-\-|^$$' $(srcdir)/command-lines.in | $(AWK) 'BEGIN {ORS = "\\n\"\n\""} //' && \ | ||||
| 	  $(EGREP) -v '^#|\-\-\-|^$$' $(srcdir)/command-lines.in | $(AWK) 'BEGIN {ORS = "\\n\"\n\""} //' && \ | ||||
| 	  echo "\\n\";" \ | ||||
| 	) > $@ | ||||
|  | ||||
| $(SOURCES:%.c=%.d) $(SOURCES2:%.c=%.d): command-lines-input.h command-count.h cmds.h | ||||
| $(SOURCES:%.c=%.o) $(SOURCES2:%.c=%.o): command-lines-input.h command-count.h cmds.h | ||||
|  | ||||
| ifneq ("$(CFLOW_CMD)", "") | ||||
| CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES)) | ||||
|   | ||||
							
								
								
									
										44
									
								
								tools/args.h
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								tools/args.h
									
									
									
									
									
								
							| @@ -244,6 +244,9 @@ arg(locktype_ARG, '\0', "locktype", locktype_VAL, 0, 0, | ||||
| arg(logonly_ARG, '\0', "logonly", 0, 0, 0, | ||||
|     "Suppress command report and display only log report.\n") | ||||
|  | ||||
| arg(longhelp_ARG, '\0', "longhelp", 0, 0, 0, | ||||
|     "Display long help text.\n") | ||||
|  | ||||
| arg(maxrecoveryrate_ARG, '\0', "maxrecoveryrate", sizekb_VAL, 0, 0, | ||||
|     "Sets the maximum recovery rate for a RAID LV.  The rate value\n" | ||||
|     "is an amount of data per second for each device in the array.\n" | ||||
| @@ -543,7 +546,7 @@ arg(shared_ARG, '\0', "shared", 0, 0, 0, | ||||
| arg(sinceversion_ARG, '\0', "sinceversion", string_VAL, 0, 0, | ||||
|     "Specify an LVM version in x.y.z format where x is the major version,\n" | ||||
|     "the y is the minor version and z is the patchlevel (e.g. 2.2.106).\n" | ||||
|     "This option is currently applicable only with --type new\n" | ||||
|     "This option is currently applicable only with --typeconfig new\n" | ||||
|     "to display all configuration settings introduced since given version.\n") | ||||
|  | ||||
| arg(splitcache_ARG, '\0', "splitcache", 0, 0, 0, | ||||
| @@ -586,9 +589,12 @@ arg(stripes_long_ARG, '\0', "stripes", number_VAL, 0, 0, | ||||
|     "existing allocated space, only newly allocated space can be striped.\n") | ||||
|  | ||||
| arg(swapmetadata_ARG, '\0', "swapmetadata", 0, 0, 0, | ||||
|     "Remove the metadata LV in a pool and replace it with another specified LV.\n" | ||||
|     "The removed LV is preserved and given the name of the LV that replaced it.\n" | ||||
|     "Used for repair only.\n") | ||||
|     "Extracts the metadata LV from a pool and replaces it with another specified LV.\n" | ||||
|     "The extracted LV is preserved and given the name of the LV that replaced it.\n" | ||||
|     "Use for repair only. When the metadata LV is swapped out of the pool, it can\n" | ||||
|     "be activated directly and used with thin provisioning tools:\n" | ||||
|     "\\fBcache_dump\\fP(8), \\fBcache_repair\\fP(8), \\fBcache_restore\\fP(8),\n" | ||||
|     "\\fBthin_dump\\fP(8), \\fBthin_repair\\fP(8), \\fBthin_restore\\fP(8).\n") | ||||
|  | ||||
| arg(syncaction_ARG, '\0', "syncaction", syncaction_VAL, 0, 0, | ||||
|     "Initiate different types of RAID synchronization.\n" | ||||
| @@ -640,7 +646,16 @@ arg(trustcache_ARG, '\0', "trustcache", 0, 0, 0, | ||||
|     "Avoids certain device scanning during command processing. Do not use.\n") | ||||
|  | ||||
| arg(type_ARG, '\0', "type", segtype_VAL, 0, 0, | ||||
|     "Specifies an LV type, or \"segment type\".\n") | ||||
|     "Specifies an LV type, or \"segment type\".\n" | ||||
|     "See usage definitions for specific ways to use these types.\n" | ||||
|     "For more information about redundancy and performance (\\fBraid\\fP<N>, \\fBmirror\\fP, \\fBstriped\\fP, \\fBlinear\\fP) see \\fBlvmraid\\fP(7).\n" | ||||
|     "For thin provisioning (\\fBthin\\fP, \\fBthin-pool\\fP) see \\fBlvmthin\\fP(7).\n" | ||||
|     "For performance caching (\\fBcache\\fP, \\fBcache-pool\\fP) see \\fBlvmcache\\fP(7).\n" | ||||
|     "For copy-on-write snapshots (\\fBsnapshot\\fP) see usage definitions.\n" | ||||
|     "Several commands omit an explicit type option because the type\n" | ||||
|     "is inferred from other options or shortcuts\n" | ||||
|     "(e.g. --stripes, --mirrors, --snapshot, --virtualsize, --thin, --cache).\n" | ||||
|     "Use inferred types with care because it can lead to unexpected results.\n") | ||||
|  | ||||
| arg(unbuffered_ARG, '\0', "unbuffered", 0, 0, 0, | ||||
|     "Produce output immediately without sorting or aligning the columns properly.\n") | ||||
| @@ -666,10 +681,12 @@ arg(unconfigured_ARG, '\0', "unconfigured", 0, 0, 0, | ||||
|     "Internal option used for generating config file during build.\n") | ||||
|  | ||||
| arg(units_ARG, '\0', "units", units_VAL, 0, 0, | ||||
|     "All sizes are output in these units: (h)uman-readable, (b)ytes, (s)ectors,\n" | ||||
|     "(k)ilobytes, (m)egabytes, (g)igabytes, (t)erabytes, (p)etabytes, (e)xabytes.\n" | ||||
|     "Capitalise to use multiples of 1000 (S.I.) instead of 1024. Can also specify\n" | ||||
|     "custom units e.g. --units 3M.\n") | ||||
|     "All sizes are output in these units:\n" | ||||
|     "human-(r)eadable with '<' rounding indicator,\n" | ||||
|     "(h)uman-readable, (b)ytes, (s)ectors, (k)ilobytes, (m)egabytes,\n" | ||||
|     "(g)igabytes, (t)erabytes, (p)etabytes, (e)xabytes.\n" | ||||
|     "Capitalise to use multiples of 1000 (S.I.) instead of 1024.\n" | ||||
|     "Custom units can be specified, e.g. --units 3M.\n") | ||||
|  | ||||
| arg(unquoted_ARG, '\0', "unquoted", 0, 0, 0, | ||||
|     "When used with --nameprefixes, output values in the field=value\n" | ||||
| @@ -920,8 +937,8 @@ arg(force_ARG, 'f', "force", 0, ARG_COUNTABLE, 0, | ||||
| /* Not used. */ | ||||
| arg(full_ARG, 'f', "full", 0, 0, 0, NULL) | ||||
|  | ||||
| arg(help_ARG, 'h', "help", 0, ARG_COUNTABLE, 0, | ||||
|     "Display help text. Repeat this option for more information.\n") | ||||
| arg(help_ARG, 'h', "help", 0, 0, 0, | ||||
|     "Display help text.\n") | ||||
|  | ||||
| arg(cache_ARG, 'H', "cache", 0, 0, 0, | ||||
|     "Specifies the command is handling a cache LV or cache pool.\n" | ||||
| @@ -1015,7 +1032,7 @@ arg(list_ARG, 'l', "list", 0, 0, 0, | ||||
|     "#dumpconfig\n" | ||||
|     "#config\n" | ||||
|     "List config settings with summarizing comment. This is the same as using\n" | ||||
|     "options --type list --withsummary.\n" | ||||
|     "options --typeconfig list --withsummary.\n" | ||||
|     "#vgcfgrestore\n" | ||||
|     "List metadata backup and archive files pertaining to the VG.\n" | ||||
|     "May be used with --file. Does not restore the VG.\n" | ||||
| @@ -1363,7 +1380,8 @@ arg(resizeable_ARG, 'x', "resizeable", bool_VAL, 0, 0, | ||||
|  | ||||
| arg(yes_ARG, 'y', "yes", 0, 0, 0, | ||||
|     "Do not prompt for confirmation interactively but always assume the\n" | ||||
|     "answer yes. Use with extreme caution.\n") | ||||
|     "answer yes. Use with extreme caution.\n" | ||||
|     "(For automatic no, see -qq.)\n") | ||||
|  | ||||
| arg(zero_ARG, 'Z', "zero", bool_VAL, 0, 0, | ||||
|     "#lvchange\n" | ||||
|   | ||||
| @@ -187,23 +187,9 @@ | ||||
| # OO_ALL is included in every command automatically. | ||||
| # | ||||
| OO_ALL: --commandprofile String, --config String, --debug, | ||||
| --driverloaded Bool, --help, --profile String, --quiet, | ||||
| --driverloaded Bool, --help, --longhelp, --profile String, --quiet, | ||||
| --verbose, --version, --yes, --test | ||||
|  | ||||
| # | ||||
| # This list only applies to printing the usage text. | ||||
| # These common options are displayed once at the end of | ||||
| # a given command's usage.  This is done to avoid excessive | ||||
| # repetition of common options, which may obscure the more | ||||
| # interesting and relevant parts of a common prototype. | ||||
| # This definition is *only* used when generating the command | ||||
| # usage strings, and is the basis for the division between | ||||
| # the "usage" and "usage_common" strings. This OO defn does | ||||
| # not relate to which optional opts are accepted by commands, | ||||
| # which is defined by the OO line. | ||||
| # | ||||
| OO_USAGE_COMMON: OO_ALL, --force, --noudevsync | ||||
|  | ||||
| # | ||||
| # options for pvs, lvs, vgs, fullreport | ||||
| # | ||||
| @@ -250,7 +236,9 @@ OO_LVCHANGE_META: --addtag Tag, --deltag Tag, | ||||
| lvchange OO_LVCHANGE_META VG|LV|Tag|Select ... | ||||
| OO: --activate Active, OO_LVCHANGE | ||||
| ID: lvchange_properties | ||||
| DESC: Change a general LV property. | ||||
| DESC: Change a general LV attribute. | ||||
| DESC: For options listed in parentheses, any one is | ||||
| DESC: required, after which the others are optional. | ||||
| RULE: all not lv_is_pvmove lv_is_mirror_log lv_is_mirror_image | ||||
| RULE: all and lv_is_vg_writable | ||||
| RULE: --contiguous not --alloc | ||||
| @@ -454,17 +442,36 @@ DESC: Convert LV to type thin-pool. | ||||
| RULE: all and lv_is_visible | ||||
| RULE: all not lv_is_locked lv_is_origin lv_is_merging_origin lv_is_external_origin lv_is_virtual | ||||
|  | ||||
| # alternate form of lvconvert --type thin-pool | ||||
| # deprecated because of non-standard syntax (missing positional arg) | ||||
| # Commands in this form are converted to standard form so that | ||||
| # the validation of LV types and rules specified above will apply. | ||||
| lvconvert --thinpool LV_linear_striped_raid_cache | ||||
| # This command syntax has two different meanings depending on | ||||
| # whether the LV pos arg is already a thin pool or not. | ||||
| # | ||||
| # 1. When the LV arg is not a pool, this command converts | ||||
| # the LV into a pool, optionally using a specified meta LV. | ||||
| # This is an alternate form of the primary command: | ||||
| # lvconvert --type thin-pool LV | ||||
| # | ||||
| # 2. When the LV is is already a pool and a meta LV is specified, | ||||
| # the meta LV is swapped.  Swapping a meta LV is a very specialized | ||||
| # operation that users should never use. | ||||
| # This is an alternate form of the primary command: | ||||
| # lvconvert --swapmetadata --poolmetadata LV LV | ||||
| # | ||||
| # The command def cannot include --poolmetadata as a required | ||||
| # option, otherwise 1 would not pass, so the validation of | ||||
| # this option cannot be done by the command defs, but has to | ||||
| # be done ad hoc in the lvconvert implementation. | ||||
| # | ||||
| # This command syntax is deprecated, and the primary forms | ||||
| # of creating a pool or swapping metadata should be used. | ||||
|  | ||||
| lvconvert --thinpool LV_linear_striped_raid_cache_thinpool | ||||
| OO: --type thin-pool, --stripes_long Number, --stripesize SizeKB, | ||||
| --discards Discards, --zero Bool, OO_LVCONVERT_POOL, OO_LVCONVERT | ||||
| OP: PV ... | ||||
| ID: lvconvert_to_thinpool_noarg | ||||
| ID: lvconvert_to_thinpool_or_swap_metadata | ||||
| DESC: Convert LV to type thin-pool (variant, use --type thin-pool). | ||||
| FLAGS: SECONDARY_SYNTAX | ||||
| DESC: Swap metadata LV in a thin pool (variant, use --swapmetadata). | ||||
| FLAGS: PREVIOUS_SYNTAX | ||||
|  | ||||
| --- | ||||
|  | ||||
| @@ -475,17 +482,36 @@ OP: PV ... | ||||
| ID: lvconvert_to_cachepool | ||||
| DESC: Convert LV to type cache-pool. | ||||
|  | ||||
| # alternate form of lvconvert --type cache-pool | ||||
| # deprecated because of non-standard syntax (missing positional arg) | ||||
| # Commands in this form are converted to standard form so that | ||||
| # the validation of LV types and rules specified above will apply. | ||||
| lvconvert --cachepool LV_linear_striped_raid | ||||
| # This command syntax has two different meanings depending on | ||||
| # whether the LV pos arg is already a cache pool or not. | ||||
| # | ||||
| # 1. When the LV arg is not a pool, this command converts | ||||
| # the LV into a pool, optionally using a specified meta LV. | ||||
| # This is an alternate form of the primary command: | ||||
| # lvconvert --type cache-pool LV | ||||
| # | ||||
| # 2. When the LV is is already a pool and a meta LV is specified, | ||||
| # the meta LV is swapped.  Swapping a meta LV is a very specialized | ||||
| # operation that users should never use. | ||||
| # This is an alternate form of the primary command: | ||||
| # lvconvert --swapmetadata --poolmetadata LV LV | ||||
| # | ||||
| # The command def cannot include --poolmetadata as a required | ||||
| # option, otherwise 1 would not pass, so the validation of | ||||
| # this option cannot be done by the command defs, but has to | ||||
| # be done ad hoc in the lvconvert implementation. | ||||
| # | ||||
| # This command syntax is deprecated, and the primary forms | ||||
| # of creating a pool or swapping metadata should be used. | ||||
|  | ||||
| lvconvert --cachepool LV_linear_striped_raid_cachepool | ||||
| OO: --type cache-pool, OO_LVCONVERT_POOL, OO_LVCONVERT, | ||||
| --cachemode CacheMode, --cachepolicy String, --cachesettings String | ||||
| OP: PV ... | ||||
| ID: lvconvert_to_cachepool_noarg | ||||
| ID: lvconvert_to_cachepool_or_swap_metadata | ||||
| DESC: Convert LV to type cache-pool (variant, use --type cache-pool). | ||||
| FLAGS: SECONDARY_SYNTAX | ||||
| DESC: Swap metadata LV in a cache pool (variant, use --swapmetadata). | ||||
| FLAGS: PREVIOUS_SYNTAX | ||||
|  | ||||
| --- | ||||
|  | ||||
| @@ -1088,12 +1114,17 @@ ID: lvdisplay_general | ||||
|  | ||||
| --- | ||||
|  | ||||
| # --type is an option in lvextend/lvresize only so that the specified type | ||||
| # value can be checked to match the existing type; using it doesn't | ||||
| # currently enable any different behavior. | ||||
|  | ||||
| # --extents is not specified; it's an automatic alternative for --size | ||||
|  | ||||
| lvextend --size SizeMB LV | ||||
| OO: --alloc Alloc, --autobackup Bool, --force, --mirrors SNumber, | ||||
| --nofsck, --nosync, --noudevsync, --reportformat ReportFmt, --resizefs, | ||||
| --stripes Number, --stripesize SizeKB, --poolmetadatasize SizeMB | ||||
| --stripes Number, --stripesize SizeKB, --poolmetadatasize SizeMB, | ||||
| --type SegType | ||||
| OP: PV ... | ||||
| ID: lvextend_by_size | ||||
| DESC: Extend an LV by a specified size. | ||||
| @@ -1101,7 +1132,8 @@ DESC: Extend an LV by a specified size. | ||||
| lvextend LV PV ... | ||||
| OO: --alloc Alloc, --autobackup Bool, --force, --mirrors SNumber, | ||||
| --nofsck, --nosync, --noudevsync, | ||||
| --reportformat ReportFmt, --resizefs, --stripes Number, --stripesize SizeKB | ||||
| --reportformat ReportFmt, --resizefs, --stripes Number, --stripesize SizeKB, | ||||
| --type SegType | ||||
| ID: lvextend_by_pv | ||||
| DESC: Extend an LV by specified PV extents. | ||||
| FLAGS: SECONDARY_SYNTAX | ||||
| @@ -1109,7 +1141,8 @@ FLAGS: SECONDARY_SYNTAX | ||||
| lvextend --poolmetadatasize SizeMB LV_thinpool | ||||
| OO: --alloc Alloc, --autobackup Bool, --force, --mirrors SNumber, | ||||
| --nofsck, --nosync, --noudevsync, | ||||
| --reportformat ReportFmt, --stripes Number, --stripesize SizeKB | ||||
| --reportformat ReportFmt, --stripes Number, --stripesize SizeKB, | ||||
| --type SegType | ||||
| OP: PV ... | ||||
| ID: lvextend_pool_metadata_by_size | ||||
| DESC: Extend a pool metadata SubLV by a specified size. | ||||
| @@ -1117,7 +1150,8 @@ DESC: Extend a pool metadata SubLV by a specified size. | ||||
| lvextend --usepolicies LV_thinpool_snapshot | ||||
| OO: --alloc Alloc, --autobackup Bool, --force, --mirrors SNumber, | ||||
| --nofsck, --nosync, --noudevsync, | ||||
| --reportformat ReportFmt, --resizefs | ||||
| --reportformat ReportFmt, --resizefs, | ||||
| --type SegType | ||||
| OP: PV ... | ||||
| ID: lvextend_by_policy | ||||
| DESC: Extend an LV according to a predefined policy. | ||||
| @@ -1155,10 +1189,15 @@ ID: lvrename_lv_lv | ||||
|  | ||||
| --- | ||||
|  | ||||
| # --type is an option in lvextend/lvresize only so that the specified type | ||||
| # value can be checked to match the existing type; using it doesn't | ||||
| # currently enable any different behavior. | ||||
|  | ||||
| lvresize --size SizeMB LV | ||||
| OO: --alloc Alloc, --autobackup Bool, --force, | ||||
| --nofsck, --nosync, --noudevsync, --reportformat ReportFmt, --resizefs, | ||||
| --stripes Number, --stripesize SizeKB, --poolmetadatasize SizeMB | ||||
| --stripes Number, --stripesize SizeKB, --poolmetadatasize SizeMB, | ||||
| --type SegType | ||||
| OP: PV ... | ||||
| ID: lvresize_by_size | ||||
| DESC: Resize an LV by a specified size. | ||||
| @@ -1166,7 +1205,8 @@ DESC: Resize an LV by a specified size. | ||||
| lvresize LV PV ... | ||||
| OO: --alloc Alloc, --autobackup Bool, --force, | ||||
| --nofsck, --nosync, --noudevsync, | ||||
| --reportformat ReportFmt, --resizefs, --stripes Number, --stripesize SizeKB | ||||
| --reportformat ReportFmt, --resizefs, --stripes Number, --stripesize SizeKB, | ||||
| --type SegType | ||||
| ID: lvresize_by_pv | ||||
| DESC: Resize an LV by specified PV extents. | ||||
| FLAGS: SECONDARY_SYNTAX | ||||
| @@ -1174,7 +1214,8 @@ FLAGS: SECONDARY_SYNTAX | ||||
| lvresize --poolmetadatasize SizeMB LV_thinpool | ||||
| OO: --alloc Alloc, --autobackup Bool, --force, | ||||
| --nofsck, --nosync, --noudevsync, | ||||
| --reportformat ReportFmt, --stripes Number, --stripesize SizeKB | ||||
| --reportformat ReportFmt, --stripes Number, --stripesize SizeKB, | ||||
| --type SegType | ||||
| OP: PV ... | ||||
| ID: lvresize_pool_metadata_by_size | ||||
| DESC: Resize a pool metadata SubLV by a specified size. | ||||
| @@ -1355,7 +1396,9 @@ vgchange OO_VGCHANGE_META | ||||
| OO: OO_VGCHANGE | ||||
| OP: VG|Tag|Select ... | ||||
| ID: vgchange_properties | ||||
| DESC: Change a general VG property. | ||||
| DESC: Change a general VG attribute. | ||||
| DESC: For options listed in parentheses, any one is | ||||
| DESC: required, after which the others are optional. | ||||
|  | ||||
| vgchange --monitor Bool | ||||
| OO: --sysinit, --ignorelockingfailure, --poll Bool, OO_VGCHANGE | ||||
|   | ||||
							
								
								
									
										919
									
								
								tools/command.c
									
									
									
									
									
								
							
							
						
						
									
										919
									
								
								tools/command.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -69,7 +69,7 @@ struct command_name { | ||||
|  | ||||
| static inline int val_bit_is_set(uint64_t val_bits, int val_enum) | ||||
| { | ||||
| 	return (val_bits & (1 << val_enum)) ? 1 : 0; | ||||
| 	return (val_bits & (1ULL << val_enum)) ? 1 : 0; | ||||
| } | ||||
|  | ||||
| static inline uint64_t val_enum_to_bit(int val_enum) | ||||
| @@ -79,7 +79,7 @@ static inline uint64_t val_enum_to_bit(int val_enum) | ||||
|  | ||||
| static inline int lvp_bit_is_set(uint64_t lvp_bits, int lvp_enum) | ||||
| { | ||||
| 	return (lvp_bits & (1 << lvp_enum)) ? 1 : 0; | ||||
| 	return (lvp_bits & (1ULL << lvp_enum)) ? 1 : 0; | ||||
| } | ||||
|  | ||||
| static inline uint64_t lvp_enum_to_bit(int lvp_enum) | ||||
| @@ -89,7 +89,7 @@ static inline uint64_t lvp_enum_to_bit(int lvp_enum) | ||||
|  | ||||
| static inline int lvt_bit_is_set(uint64_t lvt_bits, int lvt_enum) | ||||
| { | ||||
| 	return (lvt_bits & (1 << lvt_enum)) ? 1 : 0; | ||||
| 	return (lvt_bits & (1ULL << lvt_enum)) ? 1 : 0; | ||||
| } | ||||
|  | ||||
| static inline uint64_t lvt_enum_to_bit(int lvt_enum) | ||||
| @@ -166,6 +166,8 @@ struct cmd_rule { | ||||
|  */ | ||||
| #define CMD_FLAG_ONE_REQUIRED_OPT   1  /* lvchange/vgchage require one item from required_opt_args */ | ||||
| #define CMD_FLAG_SECONDARY_SYNTAX   2  /* allows syntax variants to be suppressed in certain output */ | ||||
| #define CMD_FLAG_PREVIOUS_SYNTAX    4  /* allows syntax variants to not be advertised in output */ | ||||
| #define CMD_FLAG_PARSE_ERROR        8  /* error parsing command-lines.in def */ | ||||
|  | ||||
| /* a register of the lvm commands */ | ||||
| struct command { | ||||
| @@ -175,7 +177,7 @@ struct command { | ||||
| 	int command_enum; /* <command_id>_CMD */ | ||||
| 	int command_index; /* position in commands[] */ | ||||
|  | ||||
| 	struct command_function *functions; /* new style */ | ||||
| 	const struct command_function *functions; /* new style */ | ||||
| 	command_fn fn;                      /* old style */ | ||||
|  | ||||
| 	unsigned int cmd_flags; /* CMD_FLAG_ */ | ||||
| @@ -209,9 +211,11 @@ struct command { | ||||
| 	int pos_count; /* temp counter used by create-command */ | ||||
| }; | ||||
|  | ||||
| int define_commands(void); | ||||
| int define_commands(char *run_name); | ||||
| int command_id_to_enum(const char *str); | ||||
| void print_usage(struct command *cmd); | ||||
| void print_usage_common(struct command_name *cname, struct command *cmd); | ||||
| void print_usage(struct command *cmd, int longhelp); | ||||
| void print_usage_common_cmd(struct command_name *cname, struct command *cmd); | ||||
| void print_usage_common_lvm(struct command_name *cname, struct command *cmd); | ||||
| void factor_common_options(void); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -5726,32 +5726,32 @@ static int _stats_help(CMD_ARGS); | ||||
|  * dmsetup stats <cmd> [options] [device_name] | ||||
|  * dmstats <cmd> [options] [device_name] | ||||
|  * | ||||
|  *   clear [--allregions|--regionid id] [--alldevices|<device...>] | ||||
|  *   clear [--allregions|--regionid id] [--alldevices|<device>...] | ||||
|  *   create [--start <start> [--length <len>] | ||||
|  *       [--areas <nr_areas>] [--areasize <size>] | ||||
|  *       [--programid <id>] [--userdata <data> ] | ||||
|  *       [--bounds histogram_boundaries] [--precise] | ||||
|  *       [--alldevices|<device...>] | ||||
|  *       [--alldevices|<device>...] | ||||
|  *   create --filemap [--nogroup] | ||||
|  *       [--programid <id>] [--userdata <data> ] | ||||
|  *       [--bounds histogram_boundaries] [--precise] [<file_path>] | ||||
|  *   delete [--allprograms|--programid id] | ||||
|  *       [--allregions|--regionid id] | ||||
|  *       [--alldevices|<device...>] | ||||
|  *       [--alldevices|<device>...] | ||||
|  *   group [--alias NAME] --regions <regions> | ||||
|  *       [--allprograms|--programid id] [--alldevices|<device...>] | ||||
|  *       [--allprograms|--programid id] [--alldevices|<device>...] | ||||
|  *   list [--allprograms|--programid id] [--allregions|--regionid id] | ||||
|  *   print [--clear] [--allprograms|--programid id] | ||||
|  *       [--allregions|--regionid id] | ||||
|  *       [--alldevices|<device...>] | ||||
|  *       [--alldevices|<device>...] | ||||
|  *   report [--interval <seconds>] [--count <cnt>] | ||||
|  *       [--units <u>] [--programid <id>] [--regionid <id>] | ||||
|  *       [-o <fields>] [-O|--sort <sort_fields>] | ||||
|  *       [-S|--select <selection>] [--nameprefixes] | ||||
|  *       [--noheadings] [--separator <separator>] | ||||
|  *       [--allprograms|--programid id] [<device...>] | ||||
|  *       [--allprograms|--programid id] [<device>...] | ||||
|  *   ungroup --groupid <id> [--allprograms|--programid id] | ||||
|  *       [--alldevices|<device...>] | ||||
|  *       [--alldevices|<device>...] | ||||
|  */ | ||||
|  | ||||
| #define INDENT "\n\t    " | ||||
| @@ -5766,7 +5766,7 @@ static int _stats_help(CMD_ARGS); | ||||
| #define EXTRA_OPTS HIST_OPTS PRECISE_OPTS | ||||
| #define ALL_PROGS_OPT "[--allprograms|--programid id] " | ||||
| #define ALL_REGIONS_OPT "[--allregions|--regionid id] " | ||||
| #define ALL_DEVICES_OPT "[--alldevices|<device...>] " | ||||
| #define ALL_DEVICES_OPT "[--alldevices|<device>...] " | ||||
| #define ALL_PROGS_REGIONS_DEVICES ALL_PROGS_OPT INDENT ALL_REGIONS_OPT INDENT ALL_DEVICES_OPT | ||||
| #define FIELD_OPTS "[-o <fields>] [-O|--sort <sort_fields>]" | ||||
| #define DM_REPORT_OPTS FIELD_OPTS INDENT "[-S|--select <selection>] [--nameprefixes]" INDENT \ | ||||
| @@ -5795,7 +5795,7 @@ static struct command _stats_subcommands[] = { | ||||
| 	{"group", GROUP_OPTS, 1, -1, 1, 0, _stats_group}, | ||||
| 	{"list", ALL_PROGS_OPT ALL_REGIONS_OPT, 0, -1, 1, 0, _stats_report}, | ||||
| 	{"print", PRINT_OPTS, 0, -1, 1, 0, _stats_print}, | ||||
| 	{"report", REPORT_OPTS "[<device...>]", 0, -1, 1, 0, _stats_report}, | ||||
| 	{"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}, | ||||
| @@ -5832,27 +5832,27 @@ static struct command _dmsetup_commands[] = { | ||||
| 	  "\t    [-u|uuid <uuid>] [--addnodeonresume|--addnodeoncreate]\n" | ||||
| 	  "\t    [--readahead {[+]<sectors>|auto|none}]\n" | ||||
| 	  "\t    [-n|--notable|--table {<table>|<table_file>}]", 1, 2, 0, 0, _create}, | ||||
| 	{"remove", "[--deferred] [-f|--force] [--retry] <device>", 0, -1, 1, 0, _remove}, | ||||
| 	{"remove", "[--deferred] [-f|--force] [--retry] <device>...", 0, -1, 1, 0, _remove}, | ||||
| 	{"remove_all", "[-f|--force]", 0, 0, 0, 0, _remove_all}, | ||||
| 	{"suspend", "[--noflush] [--nolockfs] <device>", 0, -1, 1, 0, _suspend}, | ||||
| 	{"resume", "[--noflush] [--nolockfs] <device>\n" | ||||
| 	{"suspend", "[--noflush] [--nolockfs] <device>...", 0, -1, 1, 0, _suspend}, | ||||
| 	{"resume", "[--noflush] [--nolockfs] <device>...\n" | ||||
| 	  "\t       [--addnodeonresume|--addnodeoncreate]\n" | ||||
| 	  "\t       [--readahead {[+]<sectors>|auto|none}]", 0, -1, 1, 0, _resume}, | ||||
| 	  {"load", "<device> [<table>|<table_file>]", 0, 2, 0, 0, _load}, | ||||
| 	{"clear", "<device>", 0, -1, 1, 0, _clear}, | ||||
| 	{"reload", "<device> [<table>|<table_file>]", 0, 2, 0, 0, _load}, | ||||
| 	{"wipe_table", "[-f|--force] [--noflush] [--nolockfs] <device>", 1, -1, 1, 0, _error_device}, | ||||
| 	{"wipe_table", "[-f|--force] [--noflush] [--nolockfs] <device>...", 1, -1, 1, 0, _error_device}, | ||||
| 	{"rename", "<device> [--setuuid] <new_name_or_uuid>", 1, 2, 0, 0, _rename}, | ||||
| 	{"message", "<device> <sector> <message>", 2, -1, 0, 0, _message}, | ||||
| 	{"ls", "[--target <target_type>] [--exec <command>] [-o <options>] [--tree]", 0, 0, 0, 0, _ls}, | ||||
| 	{"info", "[<device>]", 0, -1, 1, 0, _info}, | ||||
| 	{"deps", "[-o <options>] [<device>]", 0, -1, 1, 0, _deps}, | ||||
| 	{"stats", "<command> [<options>] [<devices>]", 1, -1, 1, 1, _stats}, | ||||
| 	{"status", "[<device>] [--noflush] [--target <target_type>]", 0, -1, 1, 0, _status}, | ||||
| 	{"table", "[<device>] [--target <target_type>] [--showkeys]", 0, -1, 1, 0, _status}, | ||||
| 	{"info", "[<device>...]", 0, -1, 1, 0, _info}, | ||||
| 	{"deps", "[-o <options>] [<device>...]", 0, -1, 1, 0, _deps}, | ||||
| 	{"stats", "<command> [<options>] [<device>...]", 1, -1, 1, 1, _stats}, | ||||
| 	{"status", "[<device>...] [--noflush] [--target <target_type>]", 0, -1, 1, 0, _status}, | ||||
| 	{"table", "[<device>...] [--target <target_type>] [--showkeys]", 0, -1, 1, 0, _status}, | ||||
| 	{"wait", "<device> [<event_nr>] [--noflush]", 0, 2, 0, 0, _wait}, | ||||
| 	{"mknodes", "[<device>]", 0, -1, 1, 0, _mknodes}, | ||||
| 	{"mangle", "[<device>]", 0, -1, 1, 0, _mangle}, | ||||
| 	{"mknodes", "[<device>...]", 0, -1, 1, 0, _mknodes}, | ||||
| 	{"mangle", "[<device>...]", 0, -1, 1, 0, _mangle}, | ||||
| 	{"udevcreatecookie", "", 0, 0, 0, 0, _udevcreatecookie}, | ||||
| 	{"udevreleasecookie", "[<cookie>]", 0, 1, 0, 0, _udevreleasecookie}, | ||||
| 	{"udevflags", "<cookie>", 1, 1, 0, 0, _udevflags}, | ||||
| @@ -5894,8 +5894,7 @@ static void _stats_usage(FILE *out) | ||||
| 	for (i = 0; _stats_subcommands[i].name; i++) | ||||
| 		fprintf(out, "\t%s %s\n", _stats_subcommands[i].name, _stats_subcommands[i].help); | ||||
|  | ||||
| 	fprintf(out, "\n<device> may be device name or -u <uuid> or " | ||||
| 		     "-j <major> -m <minor>\n"); | ||||
| 	fprintf(out, "\n<device> may be device name or (if only one) -u <uuid> or -j <major> -m <minor>\n"); | ||||
| 	fprintf(out, "<fields> are comma-separated.  Use 'help -c' for list.\n"); | ||||
| 	fprintf(out, "\n"); | ||||
| } | ||||
| @@ -5920,7 +5919,7 @@ static void _dmsetup_usage(FILE *out) | ||||
| 	for (i = 0; _dmsetup_commands[i].name; i++) | ||||
| 		fprintf(out, "\t%s %s\n", _dmsetup_commands[i].name, _dmsetup_commands[i].help); | ||||
|  | ||||
| 	fprintf(out, "\n<device> may be device name or -u <uuid> or " | ||||
| 	fprintf(out, "\n<device> may be device name or (if only one) -u <uuid> or " | ||||
| 		     "-j <major> -m <minor>\n"); | ||||
| 	fprintf(out, "<mangling_mode> is one of 'none', 'auto' and 'hex'.\n"); | ||||
| 	fprintf(out, "<fields> are comma-separated.  Use 'help -c' for list.\n"); | ||||
|   | ||||
| @@ -739,6 +739,21 @@ static int _lvchange_writemostly(struct logical_volume *lv) | ||||
| 	struct cmd_context *cmd = lv->vg->cmd; | ||||
| 	struct lv_segment *raid_seg = first_seg(lv); | ||||
|  | ||||
| 	/* | ||||
| 	 * Prohibit writebehind and writebehind during synchronization. | ||||
| 	 * | ||||
| 	 * FIXME: we can do better once we can distingush between | ||||
| 	 *        an initial sync after a linear -> raid1 upconversion | ||||
| 	 *        and any later additions of legs, requested resyncs | ||||
| 	 *        via lvchange or leg repairs/replacements. | ||||
| 	 */ | ||||
| 	if (!lv_raid_in_sync(lv)) { | ||||
| 		log_error("Unable to change write%s on %s while it is not in-sync.", | ||||
| 			  arg_is_set(cmd, writemostly_ARG) ? "mostly" : "behind", | ||||
| 			  display_lvname(lv)); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	if (arg_is_set(cmd, writebehind_ARG)) | ||||
| 		raid_seg->writebehind = arg_uint_value(cmd, writebehind_ARG, 0); | ||||
|  | ||||
|   | ||||
| @@ -3649,6 +3649,43 @@ static int _lvconvert_combine_split_snapshot_single(struct cmd_context *cmd, | ||||
|  | ||||
| int lvconvert_combine_split_snapshot_cmd(struct cmd_context *cmd, int argc, char **argv) | ||||
| { | ||||
| 	const char *vgname = NULL; | ||||
| 	const char *lvname1; | ||||
| 	const char *lvname2; | ||||
| 	char *vglv; | ||||
| 	int vglv_sz; | ||||
|  | ||||
| 	/* | ||||
| 	 * Hack to accomodate an old parsing quirk that allowed the | ||||
| 	 * the VG name to be attached to only the LV in arg pos 1, | ||||
| 	 * i.e. lvconvert -s vgname/lvname lvname | ||||
| 	 * | ||||
| 	 * The LV name in arg pos 2 is the one that is processed | ||||
| 	 * by process_each_lv().  If that LV has no VG name, but | ||||
| 	 * the first LV does, then copy the VG name from arg pos 1 | ||||
| 	 * and add it to the LV name in arg pos 2 so that the | ||||
| 	 * standard arg parsing in process_each_lv will find it. | ||||
| 	 * | ||||
| 	 * This is the only instance in all commands. | ||||
| 	 */ | ||||
|  | ||||
| 	lvname1 = cmd->position_argv[0]; | ||||
| 	lvname2 = cmd->position_argv[1]; | ||||
|  | ||||
| 	if (strstr("/", lvname1) && !strstr("/", lvname2) && !getenv("LVM_VG_NAME")) { | ||||
| 		if (!validate_lvname_param(cmd, &vgname, &lvname1)) | ||||
| 			return_ECMD_FAILED; | ||||
|  | ||||
| 		vglv_sz = strlen(vgname) + strlen(lvname2) + 2; | ||||
| 		if (!(vglv = dm_pool_alloc(cmd->mem, vglv_sz)) || | ||||
| 		    dm_snprintf(vglv, vglv_sz, "%s/%s", vgname, lvname2) < 0) { | ||||
|        			log_error("vg/lv string alloc failed."); | ||||
| 			return_ECMD_FAILED; | ||||
| 		} | ||||
|  | ||||
| 		cmd->position_argv[1] = vglv; | ||||
| 	} | ||||
|  | ||||
| 	return process_each_lv(cmd, 1, cmd->position_argv + 1, NULL, NULL, READ_FOR_UPDATE, | ||||
| 			       NULL, NULL, &_lvconvert_combine_split_snapshot_single); | ||||
| } | ||||
| @@ -3753,51 +3790,6 @@ int lvconvert_to_pool_cmd(struct cmd_context *cmd, int argc, char **argv) | ||||
| 			       NULL, NULL, &_lvconvert_to_pool_single); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Reformats non-standard command form into standard command form. | ||||
|  * | ||||
|  * In the command variants with no position LV arg, the LV arg is taken from | ||||
|  * the --thinpool/--cachepool arg, and the position args are modified to match | ||||
|  * the standard command form. | ||||
|  */ | ||||
|  | ||||
| int lvconvert_to_pool_noarg_cmd(struct cmd_context *cmd, int argc, char **argv) | ||||
| { | ||||
| 	struct command *new_command; | ||||
| 	char *pool_data_name; | ||||
| 	int i, p; | ||||
|  | ||||
| 	switch (cmd->command->command_enum) { | ||||
| 	case lvconvert_to_thinpool_noarg_CMD: | ||||
| 		pool_data_name = (char *)arg_str_value(cmd, thinpool_ARG, NULL); | ||||
| 		new_command = get_command(lvconvert_to_thinpool_CMD); | ||||
| 		break; | ||||
| 	case lvconvert_to_cachepool_noarg_CMD: | ||||
| 		pool_data_name = (char *)arg_str_value(cmd, cachepool_ARG, NULL); | ||||
| 		new_command = get_command(lvconvert_to_cachepool_CMD); | ||||
| 		break; | ||||
| 	default: | ||||
| 		log_error(INTERNAL_ERROR "Unknown pool conversion."); | ||||
| 		return 0; | ||||
| 	}; | ||||
|  | ||||
| 	log_debug("Changing command %d:%s to standard form %d:%s", | ||||
| 		  cmd->command->command_index, cmd->command->command_id, | ||||
| 		  new_command->command_index, new_command->command_id); | ||||
|  | ||||
| 	/* Make the LV the first position arg. */ | ||||
|  | ||||
| 	p = cmd->position_argc; | ||||
| 	for (i = 0; i < cmd->position_argc; i++) | ||||
| 		cmd->position_argv[p] = cmd->position_argv[p-1]; | ||||
|  | ||||
| 	cmd->position_argv[0] = pool_data_name; | ||||
| 	cmd->position_argc++; | ||||
| 	cmd->command = new_command; | ||||
|  | ||||
| 	return lvconvert_to_pool_cmd(cmd, argc, argv); | ||||
| } | ||||
|  | ||||
| static int _lvconvert_to_cache_vol_single(struct cmd_context *cmd, | ||||
| 					 struct logical_volume *lv, | ||||
| 					 struct processing_handle *handle) | ||||
| @@ -4040,39 +4032,96 @@ int lvconvert_swap_pool_metadata_cmd(struct cmd_context *cmd, int argc, char **a | ||||
| 			       NULL, NULL, &_lvconvert_swap_pool_metadata_single); | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| int lvconvert_swap_pool_metadata_noarg_cmd(struct cmd_context *cmd, int argc, char **argv) | ||||
| static int _lvconvert_to_pool_or_swap_metadata_single(struct cmd_context *cmd, | ||||
| 					 struct logical_volume *lv, | ||||
| 					 struct processing_handle *handle) | ||||
| { | ||||
| 	struct command *new_command; | ||||
| 	char *pool_name; | ||||
| 	struct dm_list *use_pvh = NULL; | ||||
| 	int to_thinpool = 0; | ||||
| 	int to_cachepool = 0; | ||||
|  | ||||
| 	switch (cmd->command->command_enum) { | ||||
| 	case lvconvert_swap_thinpool_metadata_CMD: | ||||
| 		pool_name = (char *)arg_str_value(cmd, thinpool_ARG, NULL); | ||||
| 	case lvconvert_to_thinpool_or_swap_metadata_CMD: | ||||
| 		to_thinpool = 1; | ||||
| 		break; | ||||
| 	case lvconvert_swap_cachepool_metadata_CMD: | ||||
| 		pool_name = (char *)arg_str_value(cmd, cachepool_ARG, NULL); | ||||
| 	case lvconvert_to_cachepool_or_swap_metadata_CMD: | ||||
| 		to_cachepool = 1; | ||||
| 		break; | ||||
| 	default: | ||||
| 		log_error(INTERNAL_ERROR "Invalid lvconvert pool command"); | ||||
| 		return 0; | ||||
| 	}; | ||||
|  | ||||
| 	if (cmd->position_argc > 1) { | ||||
| 		/* First pos arg is required LV, remaining are optional PVs. */ | ||||
| 		if (!(use_pvh = create_pv_list(cmd->mem, lv->vg, cmd->position_argc - 1, cmd->position_argv + 1, 0))) | ||||
| 			return_ECMD_FAILED; | ||||
| 	} else | ||||
| 		use_pvh = &lv->vg->pvs; | ||||
|  | ||||
| 	/* | ||||
| 	 * We can finally determine if this command is supposed to create | ||||
| 	 * a pool or swap the metadata in an existing pool. | ||||
| 	 * | ||||
| 	 * This allows the ambiguous command: | ||||
| 	 * 'lvconvert --thinpool LV1 --poolmetadata LV2' to mean either: | ||||
| 	 * 1. convert LV2 to a pool using the specified meta LV2 | ||||
| 	 * 2. swap the meta lv in LV1 with LV2 | ||||
| 	 * | ||||
| 	 * In case 2, the poolmetadata option is required, but in case 1 | ||||
| 	 * it is optional.  So, the command def is not able to validate | ||||
| 	 * the required/optional option, and we have to check here | ||||
| 	 * for missing poolmetadata in case 2. | ||||
| 	 */ | ||||
| 	if (lv_is_pool(lv)) { | ||||
| 		if (!arg_is_set(cmd, poolmetadata_ARG)) { | ||||
| 			log_error("The --poolmetadata option is required to swap metadata."); | ||||
| 			return ECMD_FAILED; | ||||
| 		} | ||||
| 		return _lvconvert_swap_pool_metadata_single(cmd, lv, handle); | ||||
| 	} | ||||
|  | ||||
| 	if (!_lvconvert_to_pool(cmd, lv, to_thinpool, to_cachepool, use_pvh)) | ||||
| 		return_ECMD_FAILED; | ||||
|  | ||||
| 	return ECMD_PROCESSED; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * In the command variants with no position LV arg, the LV arg is taken from | ||||
|  * the --thinpool/--cachepool arg, and the position args are modified to match | ||||
|  * the standard command form. | ||||
|  */ | ||||
|  | ||||
| int lvconvert_to_pool_or_swap_metadata_cmd(struct cmd_context *cmd, int argc, char **argv) | ||||
| { | ||||
| 	char *pool_data_name; | ||||
| 	int i, p; | ||||
|  | ||||
| 	switch (cmd->command->command_enum) { | ||||
| 	case lvconvert_to_thinpool_or_swap_metadata_CMD: | ||||
| 		pool_data_name = (char *)arg_str_value(cmd, thinpool_ARG, NULL); | ||||
| 		break; | ||||
| 	case lvconvert_to_cachepool_or_swap_metadata_CMD: | ||||
| 		pool_data_name = (char *)arg_str_value(cmd, cachepool_ARG, NULL); | ||||
| 		break; | ||||
| 	default: | ||||
| 		log_error(INTERNAL_ERROR "Unknown pool conversion."); | ||||
| 		return 0; | ||||
| 	}; | ||||
|  | ||||
| 	new_command = get_command(lvconvert_swap_pool_metadata_CMD); | ||||
|  | ||||
| 	log_debug("Changing command %d:%s to standard form %d:%s", | ||||
| 		  cmd->command->command_index, cmd->command->command_id, | ||||
| 		  new_command->command_index, new_command->command_id); | ||||
|  | ||||
| 	/* Make the LV the first position arg. */ | ||||
|  | ||||
| 	cmd->position_argv[0] = pool_name; | ||||
| 	cmd->position_argc++; | ||||
| 	cmd->command = new_command; | ||||
| 	p = cmd->position_argc; | ||||
| 	for (i = 0; i < cmd->position_argc; i++) | ||||
| 		cmd->position_argv[p] = cmd->position_argv[p-1]; | ||||
|  | ||||
| 	return lvconvert_swap_pool_metadata_cmd(cmd, argc, argv); | ||||
| 	cmd->position_argv[0] = pool_data_name; | ||||
| 	cmd->position_argc++; | ||||
|  | ||||
| 	return process_each_lv(cmd, 1, cmd->position_argv, NULL, NULL, READ_FOR_UPDATE, | ||||
| 			       NULL, NULL, &_lvconvert_to_pool_or_swap_metadata_single); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static int _lvconvert_merge_thin_single(struct cmd_context *cmd, | ||||
| 					 struct logical_volume *lv, | ||||
|   | ||||
| @@ -32,7 +32,7 @@ void *cmdlib_lvm2_init(unsigned static_compile); | ||||
| void lvm_fin(struct cmd_context *cmd); | ||||
|  | ||||
| struct cmd_context *init_lvm(unsigned set_connections, unsigned set_filters); | ||||
| void lvm_register_commands(void); | ||||
| int lvm_register_commands(char *name); | ||||
| int lvm_split(char *str, int *argc, char **argv, int max); | ||||
| int lvm_run_command(struct cmd_context *cmd, int argc, char **argv); | ||||
| int lvm_return_code(int ret); | ||||
|   | ||||
| @@ -34,7 +34,8 @@ void *cmdlib_lvm2_init(unsigned static_compile) | ||||
| 	if (!(cmd = init_lvm(1, 1))) | ||||
| 		return NULL; | ||||
|  | ||||
| 	lvm_register_commands(); | ||||
| 	if (!lvm_register_commands(NULL)) | ||||
| 		return NULL; | ||||
|  | ||||
| 	return (void *) cmd; | ||||
| } | ||||
|   | ||||
| @@ -109,7 +109,7 @@ static struct cmdline_context _cmdline; | ||||
|  * to use these functions instead of the old per-command-name function. | ||||
|  * For now, any command id not included here uses the old command fn. | ||||
|  */ | ||||
| struct command_function command_functions[CMD_COUNT] = { | ||||
| static const struct command_function command_functions[CMD_COUNT] = { | ||||
| 	{ lvmconfig_general_CMD, lvmconfig }, | ||||
| 	{ lvchange_properties_CMD, lvchange_properties_cmd }, | ||||
| 	{ lvchange_resync_CMD, lvchange_resync_cmd }, | ||||
| @@ -135,12 +135,12 @@ struct command_function command_functions[CMD_COUNT] = { | ||||
|  | ||||
| 	/* lvconvert utilities for creating/maintaining thin and cache objects. */ | ||||
| 	{ lvconvert_to_thinpool_CMD,			lvconvert_to_pool_cmd }, | ||||
| 	{ lvconvert_to_thinpool_noarg_CMD,		lvconvert_to_pool_noarg_cmd }, | ||||
| 	{ lvconvert_to_cachepool_CMD,			lvconvert_to_pool_cmd }, | ||||
| 	{ lvconvert_to_cachepool_noarg_CMD,		lvconvert_to_pool_noarg_cmd }, | ||||
| 	{ lvconvert_to_thin_with_external_CMD,		lvconvert_to_thin_with_external_cmd }, | ||||
| 	{ lvconvert_to_cache_vol_CMD,			lvconvert_to_cache_vol_cmd }, | ||||
| 	{ lvconvert_swap_pool_metadata_CMD,		lvconvert_swap_pool_metadata_cmd }, | ||||
| 	{ lvconvert_to_thinpool_or_swap_metadata_CMD,   lvconvert_to_pool_or_swap_metadata_cmd }, | ||||
| 	{ lvconvert_to_cachepool_or_swap_metadata_CMD,  lvconvert_to_pool_or_swap_metadata_cmd }, | ||||
| 	{ lvconvert_merge_thin_CMD,			lvconvert_merge_thin_cmd }, | ||||
| 	{ lvconvert_split_and_keep_cachepool_CMD,	lvconvert_split_cachepool_cmd }, | ||||
| 	{ lvconvert_split_and_remove_cachepool_CMD,	lvconvert_split_cachepool_cmd }, | ||||
| @@ -1112,7 +1112,7 @@ static struct command_name *find_command_name(const char *name) | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
| static struct command_function *_find_command_id_function(int command_enum) | ||||
| static const struct command_function *_find_command_id_function(int command_enum) | ||||
| { | ||||
| 	int i; | ||||
|  | ||||
| @@ -1126,19 +1126,23 @@ static struct command_function *_find_command_id_function(int command_enum) | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
| void lvm_register_commands(void) | ||||
| int lvm_register_commands(char *name) | ||||
| { | ||||
| 	int i; | ||||
|  | ||||
| 	/* already initialized */ | ||||
| 	if (_cmdline.commands) | ||||
| 		return 1; | ||||
|  | ||||
| 	memset(&commands, 0, sizeof(commands)); | ||||
|  | ||||
| 	/* | ||||
| 	 * populate commands[] array with command definitions | ||||
| 	 * by parsing command-lines.in/command-lines-input.h | ||||
| 	 */ | ||||
| 	if (!define_commands()) { | ||||
| 		log_error("Failed to parse command definitions."); | ||||
| 		return; | ||||
| 	if (!define_commands(name)) { | ||||
| 		log_error(INTERNAL_ERROR "Failed to parse command definitions."); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	_cmdline.commands = commands; | ||||
| @@ -1147,13 +1151,21 @@ void lvm_register_commands(void) | ||||
| 	for (i = 0; i < COMMAND_COUNT; i++) { | ||||
| 		commands[i].command_enum = command_id_to_enum(commands[i].command_id); | ||||
|  | ||||
| 		if (!commands[i].command_enum) { | ||||
| 			log_error(INTERNAL_ERROR "Failed to find command id %s.", commands[i].command_id); | ||||
| 			_cmdline.commands = NULL; | ||||
| 			_cmdline.num_commands = 0; | ||||
| 			return 0; | ||||
| 		} | ||||
|  | ||||
| 		/* new style */ | ||||
| 		commands[i].functions = _find_command_id_function(commands[i].command_enum); | ||||
|  | ||||
| 		/* old style */ | ||||
| 		if (!commands[i].functions) { | ||||
| 			struct command_name *cname = find_command_name(commands[i].name); | ||||
| 			commands[i].fn = cname->fn; | ||||
| 			if (cname) | ||||
| 				commands[i].fn = cname->fn; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -1167,6 +1179,8 @@ void lvm_register_commands(void) | ||||
|  | ||||
| 	for (i = 0; i < _cmdline.num_command_names; i++) | ||||
| 		_set_valid_args_for_command_name(i); | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| struct lv_props *get_lv_prop(int lvp_enum) | ||||
| @@ -1310,14 +1324,19 @@ static int _command_required_pos_matches(struct cmd_context *cmd, int ci, int rp | ||||
| 	if (!strcmp(cmd->name, "lvcreate") && | ||||
| 	    (rp == 0) && | ||||
| 	    val_bit_is_set(commands[ci].required_pos_args[rp].def.val_bits, vg_VAL) && | ||||
| 	    (arg_is_set(cmd, name_ARG) || arg_is_set(cmd, thinpool_ARG) || arg_is_set(cmd, cachepool_ARG))) { | ||||
| 	    (arg_is_set(cmd, name_ARG) || | ||||
| 	     arg_is_set(cmd, thinpool_ARG) || | ||||
| 	     arg_is_set(cmd, cachepool_ARG) || | ||||
| 	     getenv("LVM_VG_NAME"))) { | ||||
|  | ||||
| 		if (getenv("LVM_VG_NAME")) | ||||
| 			return 1; | ||||
|  | ||||
| 		if ((name = arg_str_value(cmd, name_ARG, NULL))) { | ||||
| 			if (strstr(name, "/") || getenv("LVM_VG_NAME")) | ||||
| 			if (strstr(name, "/")) | ||||
| 				return 1; | ||||
| 		} | ||||
|  | ||||
| 		/* FIXME: does LVM_VG_NAME also work with --thinpool/--cachepool ? */ | ||||
|  | ||||
| 		if ((name = arg_str_value(cmd, thinpool_ARG, NULL))) { | ||||
| 			if (strstr(name, "/")) | ||||
| 				return 1; | ||||
| @@ -1363,7 +1382,7 @@ static struct command *_find_command(struct cmd_context *cmd, const char *path, | ||||
| 	char buf[64]; | ||||
| 	int match_required, match_ro, match_rp, match_type, match_unused, mismatch_required; | ||||
| 	int best_i = 0, best_required = 0, best_type = 0, best_unused = 0; | ||||
| 	int close_i = 0, close_ro = 0, close_type; | ||||
| 	int close_i = 0, close_ro = 0, close_type = 0; | ||||
| 	int temp_unused_options[MAX_UNUSED_COUNT]; | ||||
| 	int temp_unused_count; | ||||
| 	int best_unused_options[MAX_UNUSED_COUNT] = { 0 }; | ||||
| @@ -1381,7 +1400,7 @@ static struct command *_find_command(struct cmd_context *cmd, const char *path, | ||||
| 			continue; | ||||
|  | ||||
| 		/* For help and version just return the first entry with matching name. */ | ||||
| 		if (arg_is_set(cmd, help_ARG) || arg_is_set(cmd, help2_ARG) || arg_is_set(cmd, version_ARG)) | ||||
| 		if (arg_is_set(cmd, help_ARG) || arg_is_set(cmd, help2_ARG) || arg_is_set(cmd, longhelp_ARG) || arg_is_set(cmd, version_ARG)) | ||||
| 			return &commands[i]; | ||||
|  | ||||
| 		match_required = 0;    /* required parameters that match */ | ||||
| @@ -1542,9 +1561,10 @@ static struct command *_find_command(struct cmd_context *cmd, const char *path, | ||||
| 	if (!best_required) { | ||||
| 		/* cmd did not have all the required opt/pos args of any command */ | ||||
| 		log_error("Failed to find a matching command definition."); | ||||
| 		log_error("Run '%s --help' for more information.", name); | ||||
| 		if (close_ro) { | ||||
| 			log_warn("Closest command usage is:"); | ||||
| 			print_usage(&_cmdline.commands[close_i]); | ||||
| 			print_usage(&_cmdline.commands[close_i], 0); | ||||
| 		} | ||||
| 		return NULL; | ||||
| 	} | ||||
| @@ -1657,7 +1677,7 @@ static void _short_usage(const char *name) | ||||
| 	log_error("Run `%s --help' for more information.", name); | ||||
| } | ||||
|  | ||||
| static int _usage(const char *name, int help_count) | ||||
| static int _usage(const char *name, int longhelp) | ||||
| { | ||||
| 	struct command_name *cname = find_command_name(name); | ||||
| 	struct command *cmd; | ||||
| @@ -1668,58 +1688,54 @@ static int _usage(const char *name, int help_count) | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	/* | ||||
| 	 * Looks at all variants of each command name and figures out | ||||
| 	 * which options are common to all variants (for compact output) | ||||
| 	 */ | ||||
|         factor_common_options(); | ||||
|  | ||||
| 	log_print("%s - %s\n", name, cname->desc); | ||||
|  | ||||
| 	/* Reduce the default output when there are several variants. */ | ||||
|  | ||||
| 	if (cname->variants < 3) | ||||
| 		longhelp = 1; | ||||
|  | ||||
| 	for (i = 0; i < COMMAND_COUNT; i++) { | ||||
| 		if (strcmp(_cmdline.commands[i].name, name)) | ||||
| 			continue; | ||||
|  | ||||
| 		if ((_cmdline.commands[i].cmd_flags & CMD_FLAG_SECONDARY_SYNTAX) && (help_count < 3)) | ||||
| 		if (_cmdline.commands[i].cmd_flags & CMD_FLAG_PREVIOUS_SYNTAX) | ||||
| 			continue; | ||||
|  | ||||
| 		print_usage(&_cmdline.commands[i]); | ||||
| 		if ((_cmdline.commands[i].cmd_flags & CMD_FLAG_SECONDARY_SYNTAX) && !longhelp) | ||||
| 			continue; | ||||
|  | ||||
| 		print_usage(&_cmdline.commands[i], longhelp); | ||||
| 		cmd = &_cmdline.commands[i]; | ||||
| 		printf("\n"); | ||||
| 	} | ||||
|  | ||||
| 	/* Common options are printed once for all variants of a command name. */ | ||||
| 	print_usage_common(cname, cmd); | ||||
|  | ||||
| 	if (help_count > 1) { | ||||
| 		/* | ||||
| 		 * Excluding commonly understood syntax style like the meanings of: | ||||
| 		 * [ ] for optional, ... for repeatable, | for one of the following, | ||||
| 		 * -- for an option name, lower case strings and digits for literals. | ||||
| 		 */ | ||||
| 		log_print("Usage notes:"); | ||||
| 		log_print(". Variable parameters are: Number, String, PV, VG, LV, Tag."); | ||||
| 		log_print(". Select indicates that a required positional parameter can"); | ||||
| 		log_print("  be omitted if the --select option is used."); | ||||
| 		log_print(". --size Number can be replaced with --extents NumberExtents."); | ||||
| 		log_print(". When --name is omitted from lvcreate, a new LV name is"); | ||||
| 		log_print("  generated with the \"lvol\" prefix and a unique numeric suffix."); | ||||
| 		log_print(". The required VG parameter in lvcreate may be omitted when"); | ||||
| 		log_print("  the VG name is included in another option, e.g. --name VG/LV."); | ||||
| 		log_print(". For required options listed in parentheses, e.g. (--A, --B),"); | ||||
| 		log_print("  any one is required, after which the others are optional."); | ||||
| 		log_print(". The _new suffix indicates the VG or LV must not yet exist."); | ||||
| 		log_print(". LV followed by _<type> indicates that an LV of the given type"); | ||||
| 		log_print("  is required.  (raid represents any raid<N> type.)"); | ||||
| 		log_print(". Input units are always treated as base two values, regardless of"); | ||||
| 		log_print("  unit capitalization, e.g. 'k' and 'K' both refer to 1024."); | ||||
| 		log_print(". The default input unit is specified by letter, followed by |unit"); | ||||
| 		log_print("  which represents other possible input units: bBsSkKmMgGtTpPeE."); | ||||
| 		log_print(". Output units can be specified with the --units option, for which"); | ||||
| 		log_print("  lower/upper case letters refer to base 2/10 values."); | ||||
| 		log_print(". Use --help --help --help to print secondary command syntax"); | ||||
| 		log_print("  formats that are recognized, e.g. for compatibility."); | ||||
| 		log_print(". See man pages for short option equivalents of long option names,"); | ||||
| 		log_print("  and for more detailed descriptions of variable parameters."); | ||||
| 	} | ||||
| 	if (longhelp) { | ||||
| 		print_usage_common_cmd(cname, cmd); | ||||
| 		print_usage_common_lvm(cname, cmd); | ||||
| 	} else | ||||
| 		log_print("Use --longhelp to show all options."); | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| static void _usage_all(void) | ||||
| { | ||||
| 	int i; | ||||
|  | ||||
| 	for (i = 0; i < MAX_COMMAND_NAMES; i++) { | ||||
| 		if (!command_names[i].name) | ||||
| 			break; | ||||
| 		_usage(command_names[i].name, 0); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Sets up the arguments to pass to getopt_long(). | ||||
|  * | ||||
| @@ -2154,11 +2170,10 @@ static int _get_settings(struct cmd_context *cmd) | ||||
|  | ||||
| static int _process_common_commands(struct cmd_context *cmd) | ||||
| { | ||||
| 	if (arg_is_set(cmd, help_ARG) || arg_is_set(cmd, help2_ARG)) { | ||||
| 		_usage(cmd->name, arg_count(cmd, help_ARG)); | ||||
|  | ||||
| 		if (arg_count(cmd, help_ARG) < 2) | ||||
| 			log_print("(Use --help --help for usage notes.)"); | ||||
| 	if (arg_is_set(cmd, help_ARG) || | ||||
| 	    arg_is_set(cmd, longhelp_ARG) || | ||||
| 	    arg_is_set(cmd, help2_ARG)) { | ||||
| 		_usage(cmd->name, arg_is_set(cmd, longhelp_ARG)); | ||||
| 		return ECMD_PROCESSED; | ||||
| 	} | ||||
|  | ||||
| @@ -2191,6 +2206,8 @@ int help(struct cmd_context *cmd __attribute__((unused)), int argc, char **argv) | ||||
|  | ||||
| 	if (!argc) | ||||
| 		_display_help(); | ||||
| 	else if (argc == 1 && !strcmp(argv[0], "all")) | ||||
| 		_usage_all(); | ||||
| 	else { | ||||
| 		int i; | ||||
| 		for (i = 0; i < argc; i++) | ||||
| @@ -2481,7 +2498,7 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv) | ||||
| 	/* each command should start out with sigint flag cleared */ | ||||
| 	sigint_clear(); | ||||
|  | ||||
| 	cmd->name = strdup(argv[0]); | ||||
| 	cmd->name = dm_pool_strdup(cmd->mem, argv[0]); | ||||
|  | ||||
| 	/* eliminate '-' from all options starting with -- */ | ||||
| 	for (i = 1; i < argc; i++) { | ||||
| @@ -3139,6 +3156,7 @@ int lvm2_main(int argc, char **argv) | ||||
| 	int ret, alias = 0; | ||||
| 	struct custom_fds custom_fds; | ||||
| 	struct cmd_context *cmd; | ||||
| 	char *name; | ||||
|  | ||||
| 	if (!argv) | ||||
| 		return -1; | ||||
| @@ -3180,7 +3198,17 @@ int lvm2_main(int argc, char **argv) | ||||
|  | ||||
| 	cmd->argv = argv; | ||||
|  | ||||
| 	lvm_register_commands(); | ||||
| 	if (!alias && argc == 1) | ||||
| 		name = NULL; | ||||
| 	else if (alias) | ||||
| 		name = argv[0]; | ||||
| 	else | ||||
| 		name = argv[1]; | ||||
|  | ||||
| 	if (!lvm_register_commands(name)) { | ||||
| 		ret = ECMD_FAILED; | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	if (_lvm1_fallback(cmd)) { | ||||
| 		/* Attempt to run equivalent LVM1 tool instead */ | ||||
| @@ -3236,6 +3264,6 @@ int lvm2_main(int argc, char **argv) | ||||
|  | ||||
|       out: | ||||
| 	lvm_fin(cmd); | ||||
|  | ||||
| 	return lvm_return_code(ret); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -21,7 +21,7 @@ static int _lvresize_params(struct cmd_context *cmd, int argc, char **argv, | ||||
| 	const char *cmd_name = command_name(cmd); | ||||
| 	const char *type_str = arg_str_value(cmd, type_ARG, NULL); | ||||
|  | ||||
| 	if (type_str && (lp->segtype = get_segtype_from_string(cmd, type_str))) | ||||
| 	if (type_str && !(lp->segtype = get_segtype_from_string(cmd, type_str))) | ||||
| 		return_0; | ||||
|  | ||||
| 	if (!strcmp(cmd_name, "lvreduce")) | ||||
| @@ -122,10 +122,13 @@ static int _lvresize_params(struct cmd_context *cmd, int argc, char **argv, | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	if ((lp->mirrors = arg_count(cmd, mirrors_ARG)) && | ||||
| 	    (arg_sign_value(cmd, mirrors_ARG, SIGN_NONE) == SIGN_MINUS)) { | ||||
| 		log_error("Mirrors argument may not be signed."); | ||||
| 		return 0; | ||||
| 	if (arg_is_set(cmd, mirrors_ARG)) { | ||||
| 		if (arg_sign_value(cmd, mirrors_ARG, SIGN_NONE) != SIGN_NONE) { | ||||
| 			log_error("Mirrors argument may not be signed."); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		if ((lp->mirrors = arg_uint_value(cmd, mirrors_ARG, 0))) | ||||
| 			lp->mirrors++; | ||||
| 	} | ||||
|  | ||||
| 	if ((lp->stripes = arg_uint_value(cmd, stripes_ARG, 0)) && | ||||
|   | ||||
| @@ -3362,10 +3362,10 @@ static int _get_arg_lvnames(struct cmd_context *cmd, | ||||
|  * came up with its own inconsistent approach. | ||||
|  * | ||||
|  * In this case, when the position arg is a single name, it is treated as an LV | ||||
|  * name (not a VG name).  This leaves the VG unknown.  So, other option values | ||||
|  * must be searched for a VG name.  If one of those option values contains a | ||||
|  * vgname/lvname value, then the VG name is extracted and used for the LV | ||||
|  * position arg. | ||||
|  * name (not a VG name).  This leaves the VG unknown.  So, other option values, | ||||
|  * or env var, must be searched for a VG name.  If one of the option values | ||||
|  * contains a vgname/lvname value, then the VG name is extracted and used for | ||||
|  * the LV position arg.  Or, if the env var has the VG name, that is used. | ||||
|  * | ||||
|  * Other option values that are searched for a VG name are: | ||||
|  * --thinpool, --cachepool. | ||||
| @@ -3375,21 +3375,21 @@ static int _get_arg_lvnames(struct cmd_context *cmd, | ||||
|  *  . add vg/lv1 to arg_lvnames | ||||
|  * | ||||
|  *  command lv1 | ||||
|  *  . error: no vg name | ||||
|  *  . error: no vg name (unless LVM_VG_NAME) | ||||
|  * | ||||
|  *  command --option vg/lv1 vg/lv2 | ||||
|  *  command --option=vg/lv1 vg/lv2 | ||||
|  *  . verify both vg names match | ||||
|  *  . add vg to arg_vgnames | ||||
|  *  . add vg/lv2 to arg_lvnames | ||||
|  * | ||||
|  *  command --option lv1 lv2 | ||||
|  *  . error: no vg name | ||||
|  *  command --option=lv1 lv2 | ||||
|  *  . error: no vg name (unless LVM_VG_NAME) | ||||
|  * | ||||
|  *  command --option vg/lv1 lv2 | ||||
|  *  command --option=vg/lv1 lv2 | ||||
|  *  . add vg to arg_vgnames | ||||
|  *  . add vg/lv2 to arg_lvnames | ||||
|  * | ||||
|  *  command --option lv1 vg/lv2 | ||||
|  *  command --option=lv1 vg/lv2 | ||||
|  *  . add vg to arg_vgnames | ||||
|  *  . add vg/lv2 to arg_lvnames | ||||
|  */ | ||||
| @@ -3405,6 +3405,7 @@ static int _get_arg_lvnames_using_options(struct cmd_context *cmd, | ||||
| 	const char *pos_vgname = NULL; | ||||
| 	const char *opt_vgname = NULL; | ||||
| 	const char *pos_lvname = NULL; | ||||
| 	const char *env_vgname = NULL; | ||||
| 	const char *use_vgname = NULL; | ||||
| 	char *tmp_name; | ||||
| 	char *split; | ||||
| @@ -3434,10 +3435,18 @@ static int _get_arg_lvnames_using_options(struct cmd_context *cmd, | ||||
| 		return ECMD_PROCESSED; | ||||
| 	} | ||||
|  | ||||
| 	if (*pos_name == '/') { | ||||
| 		if (!(pos_name = skip_dev_dir(cmd, pos_name, NULL))) | ||||
| 			return ECMD_FAILED; | ||||
| 	} | ||||
|  | ||||
| 	if ((split = strchr(pos_name, '/'))) { | ||||
| 		pos_vgname = pos_name; | ||||
| 		pos_lvname = split + 1; | ||||
| 		*split = '\0'; | ||||
| 		/* | ||||
| 		 * This splits pos_name 'x/y' into pos_vgname 'x' and pos_lvname 'y' | ||||
| 		 * It skips repeated '/', e.g. x//y | ||||
| 		 * It also checks and fails for extra '/', e.g. x/y/z | ||||
| 		 */ | ||||
| 		pos_vgname = _extract_vgname(cmd, pos_name, &pos_lvname); | ||||
| 	} else { | ||||
| 		pos_lvname = pos_name; | ||||
| 		pos_vgname = NULL; | ||||
| @@ -3448,7 +3457,9 @@ static int _get_arg_lvnames_using_options(struct cmd_context *cmd, | ||||
| 	else if (arg_is_set(cmd, cachepool_ARG)) | ||||
| 		arg_name = arg_str_value(cmd, cachepool_ARG, NULL); | ||||
|  | ||||
| 	if (!pos_vgname && !arg_name) { | ||||
| 	env_vgname = _default_vgname(cmd); | ||||
|  | ||||
| 	if (!pos_vgname && !arg_name && !env_vgname) { | ||||
| 		log_error("Cannot find VG name for LV %s.", pos_lvname); | ||||
| 		return ECMD_FAILED; | ||||
| 	} | ||||
| @@ -3474,7 +3485,7 @@ static int _get_arg_lvnames_using_options(struct cmd_context *cmd, | ||||
| 		opt_vgname = NULL; | ||||
| 	} | ||||
|  | ||||
| 	if (!pos_vgname && !opt_vgname) { | ||||
| 	if (!pos_vgname && !opt_vgname && !env_vgname) { | ||||
| 		log_error("Cannot find VG name for LV %s.", pos_lvname); | ||||
| 		return ECMD_FAILED; | ||||
| 	} | ||||
| @@ -3485,7 +3496,14 @@ static int _get_arg_lvnames_using_options(struct cmd_context *cmd, | ||||
| 		return ECMD_FAILED;  | ||||
| 	} | ||||
|  | ||||
| 	use_vgname = pos_vgname ? pos_vgname : opt_vgname; | ||||
| 	if (pos_vgname) | ||||
| 		use_vgname = pos_vgname; | ||||
| 	else if (opt_vgname) | ||||
| 		use_vgname = opt_vgname; | ||||
| 	else if (env_vgname) | ||||
| 		use_vgname = env_vgname; | ||||
| 	else | ||||
| 		return_ECMD_FAILED;  | ||||
|  | ||||
| 	if (!str_list_add(cmd->mem, arg_vgnames, dm_pool_strdup(cmd->mem, use_vgname))) { | ||||
| 		log_error("strlist allocation failed."); | ||||
| @@ -5737,4 +5755,3 @@ bad: | ||||
| out: | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -274,10 +274,10 @@ int lvconvert_combine_split_snapshot_cmd(struct cmd_context *cmd, int argc, char | ||||
| int lvconvert_start_poll_cmd(struct cmd_context *cmd, int argc, char **argv); | ||||
|  | ||||
| int lvconvert_to_pool_cmd(struct cmd_context *cmd, int argc, char **argv); | ||||
| int lvconvert_to_pool_noarg_cmd(struct cmd_context *cmd, int argc, char **argv); | ||||
| int lvconvert_to_cache_vol_cmd(struct cmd_context *cmd, int argc, char **argv); | ||||
| int lvconvert_to_thin_with_external_cmd(struct cmd_context *cmd, int argc, char **argv); | ||||
| int lvconvert_swap_pool_metadata_cmd(struct cmd_context *cmd, int argc, char **argv); | ||||
| int lvconvert_to_pool_or_swap_metadata_cmd(struct cmd_context *cmd, int argc, char **argv); | ||||
| int lvconvert_merge_thin_cmd(struct cmd_context *cmd, int argc, char **argv); | ||||
| int lvconvert_split_cachepool_cmd(struct cmd_context *cmd, int argc, char **argv); | ||||
|  | ||||
|   | ||||
							
								
								
									
										16
									
								
								tools/vals.h
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								tools/vals.h
									
									
									
									
									
								
							| @@ -83,10 +83,10 @@ | ||||
|  * could be "Number[bBsSkKmMgGtTpPeE]" (with implied |), | ||||
|  * but repeating this full specification produces cluttered | ||||
|  * output, and doesn't indicate which unit is the default. | ||||
|  * "Number[units]" would be cleaner, as would a subset of | ||||
|  * "Number[Units]" would be cleaner, as would a subset of | ||||
|  * common units, e.g. "Number[kmg...]", but neither helps | ||||
|  * with default.  "Number[k|unit]" and "Number[m|unit]" show | ||||
|  * the default, and "unit" indicates that other units | ||||
|  * with default.  "Number[k|Unit]" and "Number[m|Unit]" show | ||||
|  * the default, and "Unit" indicates that other units | ||||
|  * are possible without listing them all.  This also | ||||
|  * suggests using the preferred lower case letters, because | ||||
|  * --size and other option args treat upper/lower letters | ||||
| @@ -115,15 +115,15 @@ val(activation_VAL, activation_arg, "Active", "y|n|ay") | ||||
| val(cachemode_VAL, cachemode_arg, "CacheMode", "writethrough|writeback") | ||||
| val(discards_VAL, discards_arg, "Discards", "passdown|nopassdown|ignore") | ||||
| val(mirrorlog_VAL, mirrorlog_arg, "MirrorLog", "core|disk") | ||||
| val(sizekb_VAL, size_kb_arg, "SizeKB", "Number[k|unit]") | ||||
| val(sizemb_VAL, size_mb_arg, "SizeMB", "Number[m|unit]") | ||||
| val(regionsize_VAL, regionsize_arg, "RegionSize", "Number[m|unit]") | ||||
| val(sizekb_VAL, size_kb_arg, "SizeKB", "Number[k|Unit]") | ||||
| val(sizemb_VAL, size_mb_arg, "SizeMB", "Number[m|Unit]") | ||||
| val(regionsize_VAL, regionsize_arg, "RegionSize", "Number[m|Unit]") | ||||
| val(numsigned_VAL, int_arg_with_sign, "SNumber", "[+|-]Number") | ||||
| val(numsignedper_VAL, int_arg_with_sign_and_percent, "SNumberP", "[+|-]Number[%VG|%PVS|%FREE]") | ||||
| val(permission_VAL, permission_arg, "Permission", "rw|r") | ||||
| val(metadatatype_VAL, metadatatype_arg, "MetadataType", "lvm2|lvm1") | ||||
| val(units_VAL, string_arg, "Units", "hHbBsSkKmMgGtTpPeE") | ||||
| val(segtype_VAL, segtype_arg, "SegType", "linear|striped|snapshot|mirror|raid*|thin|cache|thin-pool|cache-pool") | ||||
| val(units_VAL, string_arg, "Units", "r|R|h|H|b|B|s|S|k|K|m|M|g|G|t|T|p|P|e|E") | ||||
| val(segtype_VAL, segtype_arg, "SegType", "linear|striped|snapshot|mirror|raid|thin|cache|thin-pool|cache-pool") | ||||
| val(alloc_VAL, alloc_arg, "Alloc", "contiguous|cling|cling_by_tags|normal|anywhere|inherit") | ||||
| val(locktype_VAL, locktype_arg, "LockType", "sanlock|dlm|none") | ||||
| val(readahead_VAL, readahead_arg, "Readahead", "auto|none|NumberSectors") | ||||
|   | ||||
| @@ -23,7 +23,7 @@ ifeq ("@BUILD_LVMETAD@", "yes") | ||||
| LVM_RULES+=69-dm-lvm-metad.rules | ||||
| endif | ||||
|  | ||||
| DM_DIR=$(shell grep "\#define DM_DIR" $(top_srcdir)/libdm/misc/dm-ioctl.h | awk '{print $$3}') | ||||
| DM_DIR=$(shell $(GREP) "\#define DM_DIR" $(top_srcdir)/libdm/misc/dm-ioctl.h | $(AWK) '{print $$3}') | ||||
|  | ||||
| ifeq ("@UDEV_RULE_EXEC_DETECTION@", "yes") | ||||
| SBIN=\$$env{DM_SBIN_PATH} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user