mirror of
				git://sourceware.org/git/lvm2.git
				synced 2025-10-30 20:23:49 +03:00 
			
		
		
		
	Compare commits
	
		
			1 Commits
		
	
	
		
			v2_03_36
			...
			dev-dct-cm
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | c4cfdebd2f | 
| @@ -88,11 +88,19 @@ struct cmd_context { | ||||
| 	 * Command line and arguments. | ||||
| 	 */ | ||||
| 	const char *cmd_line; | ||||
| 	const char *name; /* needed before cmd->command is set */ | ||||
| 	struct command *command; | ||||
| 	char **argv; | ||||
| 	struct arg_values *arg_values; | ||||
| 	struct arg_values *opt_arg_values; | ||||
| 	struct dm_list arg_value_groups; | ||||
|  | ||||
| 	/* | ||||
| 	 * Position args remaining after command name | ||||
| 	 * and --options are removed from original argc/argv. | ||||
| 	 */ | ||||
| 	int position_argc; | ||||
| 	char **position_argv; | ||||
|  | ||||
| 	/* | ||||
| 	 * Format handlers. | ||||
| 	 */ | ||||
|   | ||||
| @@ -319,7 +319,6 @@ static int _lv_layout_and_role_thin(struct dm_pool *mem, | ||||
| { | ||||
| 	int top_level = 0; | ||||
| 	unsigned snap_count; | ||||
| 	struct lv_segment *seg; | ||||
|  | ||||
| 	/* non-top-level LVs */ | ||||
| 	if (lv_is_thin_pool_metadata(lv)) { | ||||
| @@ -353,7 +352,7 @@ static int _lv_layout_and_role_thin(struct dm_pool *mem, | ||||
| 			    !str_list_add_no_dup_check(mem, role, _lv_type_names[LV_TYPE_MULTITHINORIGIN])) | ||||
| 				goto_bad; | ||||
| 		} | ||||
| 		if ((seg = first_seg(lv)) && (seg->origin || seg->external_lv)) | ||||
| 		if (lv_is_thin_snapshot(lv)) | ||||
| 			if (!str_list_add(mem, role, _lv_type_names[LV_TYPE_SNAPSHOT]) || | ||||
| 			    !str_list_add_no_dup_check(mem, role, _lv_type_names[LV_TYPE_THINSNAPSHOT])) | ||||
| 				goto_bad; | ||||
|   | ||||
| @@ -1066,9 +1066,16 @@ struct lv_segment *get_only_segment_using_this_lv(const struct logical_volume *l | ||||
| * Useful functions for managing snapshots. | ||||
| */ | ||||
| int lv_is_origin(const struct logical_volume *lv); | ||||
| #define lv_is_thick_origin lv_is_origin | ||||
|  | ||||
| int lv_is_thin_origin(const struct logical_volume *lv, unsigned *snap_count); | ||||
| int lv_is_cache_origin(const struct logical_volume *lv); | ||||
| int lv_is_thin_snapshot(const struct logical_volume *lv); | ||||
|  | ||||
| int lv_is_cow(const struct logical_volume *lv); | ||||
| #define lv_is_thick_snapshot lv_is_cow | ||||
|  | ||||
| int lv_is_cache_origin(const struct logical_volume *lv); | ||||
|  | ||||
| int lv_is_merging_cow(const struct logical_volume *cow); | ||||
| uint32_t cow_max_extents(const struct logical_volume *origin, uint32_t chunk_size); | ||||
| int cow_has_min_chunks(const struct volume_group *vg, uint32_t cow_extents, uint32_t chunk_size); | ||||
|   | ||||
| @@ -748,6 +748,19 @@ int lv_is_thin_origin(const struct logical_volume *lv, unsigned int *snap_count) | ||||
| 	return r; | ||||
| } | ||||
|  | ||||
| int lv_is_thin_snapshot(const struct logical_volume *lv) | ||||
| { | ||||
| 	struct lv_segment *seg; | ||||
|  | ||||
| 	if (!lv_is_thin_volume(lv)) | ||||
| 		return 0; | ||||
|  | ||||
| 	if ((seg = first_seg(lv)) && (seg->origin || seg->external_lv)) | ||||
| 		return 1; | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Explict check of new thin pool for usability | ||||
|  * | ||||
|   | ||||
| @@ -140,6 +140,13 @@ Makefile: Makefile.in | ||||
| 	  *) echo "Creating $@" ; $(SED) -e "s+#VERSION#+$(LVM_VERSION)+;s+#DEFAULT_SYS_DIR#+$(DEFAULT_SYS_DIR)+;s+#DEFAULT_ARCHIVE_DIR#+$(DEFAULT_ARCHIVE_DIR)+;s+#DEFAULT_BACKUP_DIR#+$(DEFAULT_BACKUP_DIR)+;s+#DEFAULT_PROFILE_DIR#+$(DEFAULT_PROFILE_DIR)+;s+#DEFAULT_CACHE_DIR#+$(DEFAULT_CACHE_DIR)+;s+#DEFAULT_LOCK_DIR#+$(DEFAULT_LOCK_DIR)+;s+#CLVMD_PATH#+@CLVMD_PATH@+;s+#LVM_PATH#+@LVM_PATH@+;s+#DEFAULT_RUN_DIR#+@DEFAULT_RUN_DIR@+;s+#DEFAULT_PID_DIR#+@DEFAULT_PID_DIR@+;s+#SYSTEMD_GENERATOR_DIR#+$(SYSTEMD_GENERATOR_DIR)+;s+#DEFAULT_MANGLING#+$(DEFAULT_MANGLING)+;" $< > $@ ;; \ | ||||
| 	esac | ||||
|  | ||||
| ccmd: ../tools/create-commands.c | ||||
| 	$(CC) ../tools/create-commands.c -o ccmd | ||||
|  | ||||
| generate: ccmd | ||||
| 	./ccmd --output man -s 0 -p 1 -c lvcreate ../tools/command-lines.in > lvcreate.8.a | ||||
| 	cat lvcreate.8.a lvcreate.8.b > lvcreate.8.in | ||||
|  | ||||
| install_man5: $(MAN5) | ||||
| 	$(INSTALL) -d $(MAN5DIR) | ||||
| 	$(INSTALL_DATA) $(MAN5) $(MAN5DIR)/ | ||||
|   | ||||
| @@ -56,7 +56,7 @@ fail lvcreate -l 1 --cachepool pool8 $vg | ||||
|  | ||||
| # no size specified | ||||
| invalid lvcreate --cachepool pool $vg 2>&1 | tee err | ||||
| grep "specify either size or extents" err | ||||
| # grep "specify either size or extents" err | ||||
|  | ||||
| # Check nothing has been created yet | ||||
| check vg_field $vg lv_count 0 | ||||
|   | ||||
| @@ -23,7 +23,6 @@ lvcreate -l 1 -n lv1 $vg "$dev1" | ||||
| invalid vgextend | ||||
| # --metadatacopies => use --pvmetadatacopies | ||||
| invalid vgextend --metadatacopies 3 $vg "$dev1" 2>&1 | tee out | ||||
| grep -- "use --pvmetadatacopies" out | ||||
|  | ||||
| # VG name should exist | ||||
| fail vgextend --restoremissing $vg-invalid "$dev1" | ||||
|   | ||||
| @@ -76,6 +76,7 @@ SOURCES2 =\ | ||||
|  | ||||
| TARGETS =\ | ||||
| 	.commands \ | ||||
| 	command-lines.h \ | ||||
| 	liblvm2cmd.a \ | ||||
| 	lvm | ||||
|  | ||||
| @@ -99,7 +100,8 @@ LIB_VERSION = $(LIB_VERSION_LVM) | ||||
| CLEAN_TARGETS = liblvm2cmd.$(LIB_SUFFIX) $(TARGETS_DM) \ | ||||
| 	liblvm2cmd.$(LIB_SUFFIX).$(LIB_VERSION) lvm-static.o \ | ||||
| 	liblvm2cmd-static.a dmsetup.static lvm.static \ | ||||
| 	$(LDDEPS) .exported_symbols_generated | ||||
| 	$(LDDEPS) .exported_symbols_generated \ | ||||
| 	ccmd command-lines.h command-lines-count.h | ||||
|  | ||||
| ifeq ("@CMDLIB@", "yes") | ||||
| 	TARGETS += liblvm2cmd.$(LIB_SUFFIX).$(LIB_VERSION) | ||||
| @@ -171,6 +173,13 @@ liblvm2cmd.$(LIB_SUFFIX).$(LIB_VERSION): liblvm2cmd.$(LIB_SUFFIX) | ||||
| 	$(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 | ||||
|  | ||||
| ccmd: create-commands.c | ||||
| 	$(CC) create-commands.c -o ccmd | ||||
|  | ||||
| command-lines.h: ccmd | ||||
| 	./ccmd --output struct command-lines.in > command-lines.h | ||||
| 	./ccmd --output count command-lines.in > command-lines-count.h | ||||
|  | ||||
| ifneq ("$(CFLOW_CMD)", "") | ||||
| CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES)) | ||||
| -include $(top_builddir)/libdm/libdevmapper.cflow | ||||
|   | ||||
							
								
								
									
										407
									
								
								tools/args.h
									
									
									
									
									
								
							
							
						
						
									
										407
									
								
								tools/args.h
									
									
									
									
									
								
							| @@ -17,215 +17,216 @@ | ||||
|  * Put all long args that don't have a corresponding short option first. | ||||
|  */ | ||||
| /* *INDENT-OFF* */ | ||||
| arg(abort_ARG, '\0', "abort", NULL, 0, 0) | ||||
| arg(activationmode_ARG, '\0', "activationmode", string_arg, 0, 0) | ||||
| arg(addtag_ARG, '\0', "addtag", tag_arg, ARG_GROUPABLE, 0) | ||||
| arg(aligned_ARG, '\0', "aligned", NULL, 0, 0) | ||||
| arg(alloc_ARG, '\0', "alloc", alloc_arg, 0, 0) | ||||
| arg(atomic_ARG, '\0', "atomic", NULL, 0, 0) | ||||
| arg(atversion_ARG, '\0', "atversion", string_arg, 0, 0) | ||||
| arg(binary_ARG, '\0', "binary", NULL, 0, 0) | ||||
| arg(bootloaderareasize_ARG, '\0', "bootloaderareasize", size_mb_arg, 0, 0) | ||||
| arg(cache_long_ARG, '\0', "cache", NULL, 0, 0) | ||||
| arg(cachemode_ARG, '\0', "cachemode", cachemode_arg, 0, 0) | ||||
| arg(cachepool_ARG, '\0', "cachepool", string_arg, 0, 0) | ||||
| arg(commandprofile_ARG, '\0', "commandprofile", string_arg, 0, 0) | ||||
| arg(config_ARG, '\0', "config", string_arg, 0, 0) | ||||
| arg(configreport_ARG, '\0', "configreport", string_arg, ARG_GROUPABLE, 1) | ||||
| arg(configtype_ARG, '\0', "type", string_arg, 0, 0) | ||||
| arg(corelog_ARG, '\0', "corelog", NULL, 0, 0) | ||||
| arg(dataalignment_ARG, '\0', "dataalignment", size_kb_arg, 0, 0) | ||||
| arg(dataalignmentoffset_ARG, '\0', "dataalignmentoffset", size_kb_arg, 0, 0) | ||||
| arg(deltag_ARG, '\0', "deltag", tag_arg, ARG_GROUPABLE, 0) | ||||
| arg(detachprofile_ARG, '\0', "detachprofile", NULL, 0, 0) | ||||
| arg(discards_ARG, '\0', "discards", discards_arg, 0, 0) | ||||
| arg(driverloaded_ARG, '\0', "driverloaded", yes_no_arg, 0, 0) | ||||
| arg(errorwhenfull_ARG, '\0', "errorwhenfull", yes_no_arg, 0, 0) | ||||
| arg(force_long_ARG, '\0', "force", NULL, ARG_COUNTABLE, 0) | ||||
| arg(foreign_ARG, '\0', "foreign", NULL, 0, 0) | ||||
| arg(handlemissingpvs_ARG, '\0', "handlemissingpvs", NULL, 0, 0) | ||||
| arg(ignoreadvanced_ARG, '\0', "ignoreadvanced", NULL, 0, 0) | ||||
| arg(ignorelocal_ARG, '\0', "ignorelocal", NULL, 0, 0) | ||||
| arg(ignorelockingfailure_ARG, '\0', "ignorelockingfailure", NULL, 0, 0) | ||||
| arg(ignoremonitoring_ARG, '\0', "ignoremonitoring", NULL, 0, 0) | ||||
| arg(ignoreskippedcluster_ARG, '\0', "ignoreskippedcluster", NULL, 0, 0) | ||||
| arg(ignoreunsupported_ARG, '\0', "ignoreunsupported", NULL, 0, 0) | ||||
| arg(labelsector_ARG, '\0', "labelsector", int_arg, 0, 0) | ||||
| arg(lockopt_ARG, '\0', "lockopt", string_arg, 0, 0) | ||||
| arg(lockstart_ARG, '\0', "lockstart", NULL, 0, 0) | ||||
| arg(lockstop_ARG, '\0', "lockstop", NULL, 0, 0) | ||||
| arg(locktype_ARG, '\0', "locktype", locktype_arg, 0, 0) | ||||
| arg(logonly_ARG, '\0', "logonly", NULL, 0, 0) | ||||
| arg(maxrecoveryrate_ARG, '\0', "maxrecoveryrate", size_kb_arg, 0, 0) | ||||
| arg(merge_ARG, '\0', "merge", NULL, 0, 0) | ||||
| arg(mergedconfig_ARG, '\0', "mergedconfig", NULL, 0, 0) | ||||
| arg(metadatacopies_ARG, '\0', "metadatacopies", metadatacopies_arg, 0, 0) | ||||
| arg(metadataignore_ARG, '\0', "metadataignore", yes_no_arg, 0, 0) | ||||
| arg(metadataprofile_ARG, '\0', "metadataprofile", string_arg, 0, 0) | ||||
| arg(metadatasize_ARG, '\0', "metadatasize", size_mb_arg, 0, 0) | ||||
| arg(minor_ARG, '\0', "minor", int_arg, ARG_GROUPABLE, 0) | ||||
| arg(minrecoveryrate_ARG, '\0', "minrecoveryrate", size_kb_arg, 0, 0) | ||||
| arg(mirrorlog_ARG, '\0', "mirrorlog", mirrorlog_arg, 0, 0) | ||||
| arg(mirrorsonly_ARG, '\0', "mirrorsonly", NULL, 0, 0) | ||||
| arg(mknodes_ARG, '\0', "mknodes", NULL, 0, 0) | ||||
| arg(monitor_ARG, '\0', "monitor", yes_no_arg, 0, 0) | ||||
| arg(nameprefixes_ARG, '\0', "nameprefixes", NULL, 0, 0) | ||||
| arg(noheadings_ARG, '\0', "noheadings", NULL, 0, 0) | ||||
| arg(nohistory_ARG, '\0', "nohistory", NULL, 0, 0) | ||||
| arg(nolocking_ARG, '\0', "nolocking", NULL, 0, 0) | ||||
| arg(norestorefile_ARG, '\0', "norestorefile", NULL, 0, 0) | ||||
| arg(nosuffix_ARG, '\0', "nosuffix", NULL, 0, 0) | ||||
| arg(nosync_ARG, '\0', "nosync", NULL, 0, 0) | ||||
| arg(notifydbus_ARG, '\0', "notifydbus", NULL, 0, 0) | ||||
| arg(noudevsync_ARG, '\0', "noudevsync", NULL, 0, 0) | ||||
| arg(originname_ARG, '\0', "originname", string_arg, 0, 0) | ||||
| arg(physicalvolumesize_ARG, '\0', "setphysicalvolumesize", size_mb_arg, 0, 0) | ||||
| arg(poll_ARG, '\0', "poll", yes_no_arg, 0, 0) | ||||
| arg(polloperation_ARG, '\0', "polloperation", string_arg, 0, 0) | ||||
| arg(pooldatasize_ARG, '\0', "pooldatasize", size_mb_arg, 0, 0) | ||||
| arg(poolmetadata_ARG, '\0', "poolmetadata", string_arg, 0, 0) | ||||
| arg(poolmetadatasize_ARG, '\0', "poolmetadatasize", size_mb_arg, 0, 0) | ||||
| arg(poolmetadataspare_ARG, '\0', "poolmetadataspare", yes_no_arg, 0, 0) | ||||
| arg(profile_ARG, '\0', "profile", string_arg, 0, 0) | ||||
| arg(pvmetadatacopies_ARG, '\0', "pvmetadatacopies", int_arg, 0, 0) | ||||
| arg(raidrebuild_ARG, '\0', "raidrebuild", string_arg, ARG_GROUPABLE, 0) | ||||
| arg(raidmaxrecoveryrate_ARG, '\0', "raidmaxrecoveryrate", size_kb_arg, 0, 0) | ||||
| arg(raidminrecoveryrate_ARG, '\0', "raidminrecoveryrate", size_kb_arg, 0, 0) | ||||
| arg(raidsyncaction_ARG, '\0', "raidsyncaction", string_arg, 0, 0) | ||||
| arg(raidwritebehind_ARG, '\0', "raidwritebehind", int_arg, 0, 0) | ||||
| arg(raidwritemostly_ARG, '\0', "raidwritemostly", string_arg, ARG_GROUPABLE, 0) | ||||
| arg(readonly_ARG, '\0', "readonly", NULL, 0, 0) | ||||
| arg(refresh_ARG, '\0', "refresh", NULL, 0, 0) | ||||
| arg(removemissing_ARG, '\0', "removemissing", NULL, 0, 0) | ||||
| arg(rebuild_ARG, '\0', "rebuild", string_arg, ARG_GROUPABLE, 0) | ||||
| arg(repair_ARG, '\0', "repair", NULL, 0, 0) | ||||
| arg(replace_ARG, '\0', "replace", string_arg, ARG_GROUPABLE, 0) | ||||
| arg(reportformat_ARG, '\0', "reportformat", string_arg, 0, 0) | ||||
| arg(restorefile_ARG, '\0', "restorefile", string_arg, 0, 0) | ||||
| arg(restoremissing_ARG, '\0', "restoremissing", NULL, 0, 0) | ||||
| arg(resync_ARG, '\0', "resync", NULL, 0, 0) | ||||
| arg(rows_ARG, '\0', "rows", NULL, 0, 0) | ||||
| arg(segments_ARG, '\0', "segments", NULL, 0, 0) | ||||
| arg(separator_ARG, '\0', "separator", string_arg, 0, 0) | ||||
| arg(shared_ARG, '\0', "shared", NULL, 0, 0) | ||||
| arg(sinceversion_ARG, '\0', "sinceversion", string_arg, 0, 0) | ||||
| arg(split_ARG, '\0', "split", NULL, 0, 0) | ||||
| arg(splitcache_ARG, '\0', "splitcache", NULL, 0, 0) | ||||
| arg(splitmirrors_ARG, '\0', "splitmirrors", int_arg, 0, 0) | ||||
| arg(splitsnapshot_ARG, '\0', "splitsnapshot", NULL, 0, 0) | ||||
| arg(showdeprecated_ARG, '\0', "showdeprecated", NULL, 0, 0) | ||||
| arg(showunsupported_ARG, '\0', "showunsupported", NULL, 0, 0) | ||||
| arg(stripes_long_ARG, '\0', "stripes", int_arg, 0, 0) | ||||
| arg(syncaction_ARG, '\0', "syncaction", string_arg, 0, 0)	/* FIXME Use custom validation fn */ | ||||
| arg(sysinit_ARG, '\0', "sysinit", NULL, 0, 0) | ||||
| arg(systemid_ARG, '\0', "systemid", string_arg, 0, 0) | ||||
| arg(thinpool_ARG, '\0', "thinpool", string_arg, 0, 0) | ||||
| arg(trackchanges_ARG, '\0', "trackchanges", NULL, 0, 0) | ||||
| arg(trustcache_ARG, '\0', "trustcache", NULL, 0, 0) | ||||
| arg(type_ARG, '\0', "type", segtype_arg, 0, 0) | ||||
| arg(unbuffered_ARG, '\0', "unbuffered", NULL, 0, 0) | ||||
| arg(uncache_ARG, '\0', "uncache", NULL, 0, 0) | ||||
| arg(cachepolicy_ARG, '\0', "cachepolicy", string_arg, 0, 0) | ||||
| arg(cachesettings_ARG, '\0', "cachesettings", string_arg, ARG_GROUPABLE, 0) | ||||
| arg(unconfigured_ARG, '\0', "unconfigured", NULL, 0, 0) | ||||
| arg(units_ARG, '\0', "units", string_arg, 0, 0) | ||||
| arg(unquoted_ARG, '\0', "unquoted", NULL, 0, 0) | ||||
| arg(usepolicies_ARG, '\0', "usepolicies", NULL, 0, 0) | ||||
| arg(validate_ARG, '\0', "validate", NULL, 0, 0) | ||||
| arg(version_ARG, '\0', "version", NULL, 0, 0) | ||||
| arg(vgmetadatacopies_ARG, '\0', "vgmetadatacopies", metadatacopies_arg, 0, 0) | ||||
| arg(virtualoriginsize_ARG, '\0', "virtualoriginsize", size_mb_arg, 0, 0) | ||||
| arg(withsummary_ARG, '\0', "withsummary", NULL, 0, 0) | ||||
| arg(withcomments_ARG, '\0', "withcomments", NULL, 0, 0) | ||||
| arg(withspaces_ARG, '\0', "withspaces", NULL, 0, 0) | ||||
| arg(withversions_ARG, '\0', "withversions", NULL, 0, 0) | ||||
| arg(writebehind_ARG, '\0', "writebehind", int_arg, 0, 0) | ||||
| arg(writemostly_ARG, '\0', "writemostly", string_arg, ARG_GROUPABLE, 0) | ||||
| arg(ARG_UNUSED, '-', "", 0, 0, 0)  /* place holder for unused 0 value */ | ||||
|  | ||||
| arg(abort_ARG, '\0', "abort", 0, 0, 0) | ||||
| arg(activationmode_ARG, '\0', "activationmode", activationmode_VAL, 0, 0) | ||||
| arg(addtag_ARG, '\0', "addtag", tag_VAL, ARG_GROUPABLE, 0) | ||||
| arg(aligned_ARG, '\0', "aligned", 0, 0, 0) | ||||
| arg(alloc_ARG, '\0', "alloc", alloc_VAL, 0, 0) | ||||
| arg(atomic_ARG, '\0', "atomic", 0, 0, 0) | ||||
| arg(atversion_ARG, '\0', "atversion", string_VAL, 0, 0) | ||||
| arg(binary_ARG, '\0', "binary", 0, 0, 0) | ||||
| arg(bootloaderareasize_ARG, '\0', "bootloaderareasize", sizemb_VAL, 0, 0) | ||||
| arg(cache_long_ARG, '\0', "cache", 0, 0, 0) | ||||
| arg(cachemode_ARG, '\0', "cachemode", cachemode_VAL, 0, 0) | ||||
| arg(cachepool_ARG, '\0', "cachepool", lv_VAL, 0, 0) | ||||
| arg(commandprofile_ARG, '\0', "commandprofile", string_VAL, 0, 0) | ||||
| arg(config_ARG, '\0', "config", string_VAL, 0, 0) | ||||
| arg(configreport_ARG, '\0', "configreport", configreport_VAL, ARG_GROUPABLE, 1) | ||||
| arg(configtype_ARG, '\0', "typeconfig", configtype_VAL, 0, 0) | ||||
| arg(corelog_ARG, '\0', "corelog", 0, 0, 0) | ||||
| arg(dataalignment_ARG, '\0', "dataalignment", sizekb_VAL, 0, 0) | ||||
| arg(dataalignmentoffset_ARG, '\0', "dataalignmentoffset", sizekb_VAL, 0, 0) | ||||
| arg(deltag_ARG, '\0', "deltag", tag_VAL, ARG_GROUPABLE, 0) | ||||
| arg(detachprofile_ARG, '\0', "detachprofile", 0, 0, 0) | ||||
| arg(discards_ARG, '\0', "discards", discards_VAL, 0, 0) | ||||
| arg(driverloaded_ARG, '\0', "driverloaded", bool_VAL, 0, 0) | ||||
| arg(errorwhenfull_ARG, '\0', "errorwhenfull", bool_VAL, 0, 0) | ||||
| arg(force_long_ARG, '\0', "force", 0, ARG_COUNTABLE, 0) | ||||
| arg(foreign_ARG, '\0', "foreign", 0, 0, 0) | ||||
| arg(handlemissingpvs_ARG, '\0', "handlemissingpvs", 0, 0, 0) | ||||
| arg(ignoreadvanced_ARG, '\0', "ignoreadvanced", 0, 0, 0) | ||||
| arg(ignorelocal_ARG, '\0', "ignorelocal", 0, 0, 0) | ||||
| arg(ignorelockingfailure_ARG, '\0', "ignorelockingfailure", 0, 0, 0) | ||||
| arg(ignoremonitoring_ARG, '\0', "ignoremonitoring", 0, 0, 0) | ||||
| arg(ignoreskippedcluster_ARG, '\0', "ignoreskippedcluster", 0, 0, 0) | ||||
| arg(ignoreunsupported_ARG, '\0', "ignoreunsupported", 0, 0, 0) | ||||
| arg(labelsector_ARG, '\0', "labelsector", number_VAL, 0, 0) | ||||
| arg(lockopt_ARG, '\0', "lockopt", string_VAL, 0, 0) | ||||
| arg(lockstart_ARG, '\0', "lockstart", 0, 0, 0) | ||||
| arg(lockstop_ARG, '\0', "lockstop", 0, 0, 0) | ||||
| arg(locktype_ARG, '\0', "locktype", locktype_VAL, 0, 0) | ||||
| arg(logonly_ARG, '\0', "logonly", 0, 0, 0) | ||||
| arg(maxrecoveryrate_ARG, '\0', "maxrecoveryrate", sizekb_VAL, 0, 0) | ||||
| arg(merge_ARG, '\0', "merge", 0, 0, 0) | ||||
| arg(mergedconfig_ARG, '\0', "mergedconfig", 0, 0, 0) | ||||
| arg(metadatacopies_ARG, '\0', "metadatacopies", metadatacopies_VAL, 0, 0) | ||||
| arg(metadataignore_ARG, '\0', "metadataignore", bool_VAL, 0, 0) | ||||
| arg(metadataprofile_ARG, '\0', "metadataprofile", string_VAL, 0, 0) | ||||
| arg(metadatasize_ARG, '\0', "metadatasize", sizemb_VAL, 0, 0) | ||||
| arg(minor_ARG, '\0', "minor", number_VAL, ARG_GROUPABLE, 0) | ||||
| arg(minrecoveryrate_ARG, '\0', "minrecoveryrate", sizekb_VAL, 0, 0) | ||||
| arg(mirrorlog_ARG, '\0', "mirrorlog", mirrorlog_VAL, 0, 0) | ||||
| arg(mirrorsonly_ARG, '\0', "mirrorsonly", 0, 0, 0) | ||||
| arg(mknodes_ARG, '\0', "mknodes", 0, 0, 0) | ||||
| arg(monitor_ARG, '\0', "monitor", bool_VAL, 0, 0) | ||||
| arg(nameprefixes_ARG, '\0', "nameprefixes", 0, 0, 0) | ||||
| arg(noheadings_ARG, '\0', "noheadings", 0, 0, 0) | ||||
| arg(nohistory_ARG, '\0', "nohistory", 0, 0, 0) | ||||
| arg(nolocking_ARG, '\0', "nolocking", 0, 0, 0) | ||||
| arg(norestorefile_ARG, '\0', "norestorefile", 0, 0, 0) | ||||
| arg(nosuffix_ARG, '\0', "nosuffix", 0, 0, 0) | ||||
| arg(nosync_ARG, '\0', "nosync", 0, 0, 0) | ||||
| arg(notifydbus_ARG, '\0', "notifydbus", 0, 0, 0) | ||||
| arg(noudevsync_ARG, '\0', "noudevsync", 0, 0, 0) | ||||
| arg(originname_ARG, '\0', "originname", lv_VAL, 0, 0) | ||||
| arg(physicalvolumesize_ARG, '\0', "setphysicalvolumesize", sizemb_VAL, 0, 0) | ||||
| arg(poll_ARG, '\0', "poll", bool_VAL, 0, 0) | ||||
| arg(polloperation_ARG, '\0', "polloperation", polloperation_VAL, 0, 0) | ||||
| arg(pooldatasize_ARG, '\0', "pooldatasize", sizemb_VAL, 0, 0) | ||||
| arg(poolmetadata_ARG, '\0', "poolmetadata", lv_VAL, 0, 0) | ||||
| arg(poolmetadatasize_ARG, '\0', "poolmetadatasize", sizemb_VAL, 0, 0) | ||||
| arg(poolmetadataspare_ARG, '\0', "poolmetadataspare", bool_VAL, 0, 0) | ||||
| arg(profile_ARG, '\0', "profile", string_VAL, 0, 0) | ||||
| arg(pvmetadatacopies_ARG, '\0', "pvmetadatacopies", pvmetadatacopies_VAL, 0, 0) | ||||
| arg(raidrebuild_ARG, '\0', "raidrebuild", pv_VAL, ARG_GROUPABLE, 0) | ||||
| arg(raidmaxrecoveryrate_ARG, '\0', "raidmaxrecoveryrate", sizekb_VAL, 0, 0) | ||||
| arg(raidminrecoveryrate_ARG, '\0', "raidminrecoveryrate", sizekb_VAL, 0, 0) | ||||
| arg(raidsyncaction_ARG, '\0', "raidsyncaction", syncaction_VAL, 0, 0) | ||||
| arg(raidwritebehind_ARG, '\0', "raidwritebehind", number_VAL, 0, 0) | ||||
| arg(raidwritemostly_ARG, '\0', "raidwritemostly", writemostly_VAL, ARG_GROUPABLE, 0) | ||||
| arg(readonly_ARG, '\0', "readonly", 0, 0, 0) | ||||
| arg(refresh_ARG, '\0', "refresh", 0, 0, 0) | ||||
| arg(removemissing_ARG, '\0', "removemissing", 0, 0, 0) | ||||
| arg(rebuild_ARG, '\0', "rebuild", pv_VAL, ARG_GROUPABLE, 0) | ||||
| arg(repair_ARG, '\0', "repair", 0, 0, 0) | ||||
| arg(replace_ARG, '\0', "replace", pv_VAL, ARG_GROUPABLE, 0) | ||||
| arg(reportformat_ARG, '\0', "reportformat", reportformat_VAL, 0, 0) | ||||
| arg(restorefile_ARG, '\0', "restorefile", string_VAL, 0, 0) | ||||
| arg(restoremissing_ARG, '\0', "restoremissing", 0, 0, 0) | ||||
| arg(resync_ARG, '\0', "resync", 0, 0, 0) | ||||
| arg(rows_ARG, '\0', "rows", 0, 0, 0) | ||||
| arg(segments_ARG, '\0', "segments", 0, 0, 0) | ||||
| arg(separator_ARG, '\0', "separator", string_VAL, 0, 0) | ||||
| arg(shared_ARG, '\0', "shared", 0, 0, 0) | ||||
| arg(sinceversion_ARG, '\0', "sinceversion", string_VAL, 0, 0) | ||||
| arg(split_ARG, '\0', "split", 0, 0, 0) | ||||
| arg(splitcache_ARG, '\0', "splitcache", 0, 0, 0) | ||||
| arg(splitmirrors_ARG, '\0', "splitmirrors", number_VAL, 0, 0) | ||||
| arg(splitsnapshot_ARG, '\0', "splitsnapshot", 0, 0, 0) | ||||
| arg(showdeprecated_ARG, '\0', "showdeprecated", 0, 0, 0) | ||||
| arg(showunsupported_ARG, '\0', "showunsupported", 0, 0, 0) | ||||
| arg(stripes_long_ARG, '\0', "stripes", number_VAL, 0, 0) | ||||
| arg(syncaction_ARG, '\0', "syncaction", syncaction_VAL, 0, 0) | ||||
| arg(sysinit_ARG, '\0', "sysinit", 0, 0, 0) | ||||
| arg(systemid_ARG, '\0', "systemid", string_VAL, 0, 0) | ||||
| arg(thinpool_ARG, '\0', "thinpool", lv_VAL, 0, 0) | ||||
| arg(trackchanges_ARG, '\0', "trackchanges", 0, 0, 0) | ||||
| arg(trustcache_ARG, '\0', "trustcache", 0, 0, 0) | ||||
| arg(type_ARG, '\0', "type", segtype_VAL, 0, 0) | ||||
| arg(unbuffered_ARG, '\0', "unbuffered", 0, 0, 0) | ||||
| arg(uncache_ARG, '\0', "uncache", 0, 0, 0) | ||||
| arg(cachepolicy_ARG, '\0', "cachepolicy", string_VAL, 0, 0) | ||||
| arg(cachesettings_ARG, '\0', "cachesettings", string_VAL, ARG_GROUPABLE, 0) | ||||
| arg(unconfigured_ARG, '\0', "unconfigured", 0, 0, 0) | ||||
| arg(units_ARG, '\0', "units", units_VAL, 0, 0) | ||||
| arg(unquoted_ARG, '\0', "unquoted", 0, 0, 0) | ||||
| arg(usepolicies_ARG, '\0', "usepolicies", 0, 0, 0) | ||||
| arg(validate_ARG, '\0', "validate", 0, 0, 0) | ||||
| arg(version_ARG, '\0', "version", 0, 0, 0) | ||||
| arg(vgmetadatacopies_ARG, '\0', "vgmetadatacopies", vgmetadatacopies_VAL, 0, 0) | ||||
| arg(virtualoriginsize_ARG, '\0', "virtualoriginsize", sizemb_VAL, 0, 0) | ||||
| arg(withsummary_ARG, '\0', "withsummary", 0, 0, 0) | ||||
| arg(withcomments_ARG, '\0', "withcomments", 0, 0, 0) | ||||
| arg(withspaces_ARG, '\0', "withspaces", 0, 0, 0) | ||||
| arg(withversions_ARG, '\0', "withversions", 0, 0, 0) | ||||
| arg(writebehind_ARG, '\0', "writebehind", number_VAL, 0, 0) | ||||
| arg(writemostly_ARG, '\0', "writemostly", writemostly_VAL, ARG_GROUPABLE, 0) | ||||
|  | ||||
| /* Allow some variations */ | ||||
| arg(allocation_ARG, '\0', "allocation", yes_no_arg, 0, 0) | ||||
| arg(available_ARG, '\0', "available", activation_arg, 0, 0) | ||||
| arg(resizable_ARG, '\0', "resizable", yes_no_arg, 0, 0) | ||||
| arg(allocation_ARG, '\0', "allocation", bool_VAL, 0, 0) | ||||
| arg(available_ARG, '\0', "available", activation_VAL, 0, 0) | ||||
| arg(resizable_ARG, '\0', "resizable", bool_VAL, 0, 0) | ||||
|  | ||||
| /* | ||||
|  * ... and now the short args. | ||||
|  */ | ||||
| arg(activate_ARG, 'a', "activate", activation_arg, 0, 0) | ||||
| arg(all_ARG, 'a', "all", NULL, 0, 0) | ||||
| arg(autobackup_ARG, 'A', "autobackup", yes_no_arg, 0, 0) | ||||
| arg(activevolumegroups_ARG, 'A', "activevolumegroups", NULL, 0, 0) | ||||
| arg(background_ARG, 'b', "background", NULL, 0, 0) | ||||
| arg(backgroundfork_ARG, 'b', "background", NULL, 0, 0) | ||||
| arg(basevgname_ARG, 'n', "basevgname", string_arg, 0, 0) | ||||
| arg(blockdevice_ARG, 'b', "blockdevice", NULL, 0, 0) | ||||
| arg(chunksize_ARG, 'c', "chunksize", size_kb_arg, 0, 0) | ||||
| arg(clustered_ARG, 'c', "clustered", yes_no_arg, 0, 0) | ||||
| arg(colon_ARG, 'c', "colon", NULL, 0, 0) | ||||
| arg(columns_ARG, 'C', "columns", NULL, 0, 0) | ||||
| arg(contiguous_ARG, 'C', "contiguous", yes_no_arg, 0, 0) | ||||
| arg(debug_ARG, 'd', "debug", NULL, ARG_COUNTABLE, 0) | ||||
| arg(exported_ARG, 'e', "exported", NULL, 0, 0) | ||||
| arg(physicalextent_ARG, 'E', "physicalextent", NULL, 0, 0) | ||||
| arg(file_ARG, 'f', "file", string_arg, 0, 0) | ||||
| arg(force_ARG, 'f', "force", NULL, ARG_COUNTABLE, 0) | ||||
| arg(full_ARG, 'f', "full", NULL, 0, 0) | ||||
| arg(help_ARG, 'h', "help", NULL, 0, 0) | ||||
| arg(cache_ARG, 'H', "cache", NULL, 0, 0) | ||||
| arg(history_ARG, 'H', "history", NULL, 0, 0) | ||||
| arg(help2_ARG, '?', "", NULL, 0, 0) | ||||
| arg(import_ARG, 'i', "import", NULL, 0, 0) | ||||
| arg(interval_ARG, 'i', "interval", int_arg, 0, 0) | ||||
| arg(iop_version_ARG, 'i', "iop_version", NULL, 0, 0) | ||||
| arg(stripes_ARG, 'i', "stripes", int_arg, 0, 0) | ||||
| arg(stripesize_ARG, 'I', "stripesize", size_kb_arg, 0, 0) | ||||
| arg(logicalvolume_ARG, 'l', "logicalvolume", int_arg, 0, 0) | ||||
| arg(maxlogicalvolumes_ARG, 'l', "maxlogicalvolumes", int_arg, 0, 0) | ||||
| arg(extents_ARG, 'l', "extents", int_arg_with_sign_and_percent, 0, 0) | ||||
| arg(list_ARG, 'l', "list", NULL, 0, 0) | ||||
| arg(lvmpartition_ARG, 'l', "lvmpartition", NULL, 0, 0) | ||||
| arg(logicalextent_ARG, 'L', "logicalextent", int_arg_with_sign, 0, 0) | ||||
| arg(size_ARG, 'L', "size", size_mb_arg, 0, 0) | ||||
| arg(persistent_ARG, 'M', "persistent", yes_no_arg, 0, 0) | ||||
| arg(major_ARG, 'j', "major", int_arg, ARG_GROUPABLE, 0) | ||||
| arg(setactivationskip_ARG, 'k', "setactivationskip", yes_no_arg, 0, 0) | ||||
| arg(ignoreactivationskip_ARG, 'K', "ignoreactivationskip", NULL, 0, 0) | ||||
| arg(maps_ARG, 'm', "maps", NULL, 0, 0) | ||||
| arg(mirrors_ARG, 'm', "mirrors", int_arg_with_sign, 0, 0) | ||||
| arg(metadatatype_ARG, 'M', "metadatatype", metadatatype_arg, 0, 0) | ||||
| arg(name_ARG, 'n', "name", string_arg, 0, 0) | ||||
| arg(nofsck_ARG, 'n', "nofsck", NULL, 0, 0) | ||||
| arg(novolumegroup_ARG, 'n', "novolumegroup", NULL, 0, 0) | ||||
| arg(oldpath_ARG, 'n', "oldpath", NULL, 0, 0) | ||||
| arg(options_ARG, 'o', "options", string_arg, ARG_GROUPABLE, 0) | ||||
| arg(sort_ARG, 'O', "sort", string_arg, ARG_GROUPABLE, 0) | ||||
| arg(maxphysicalvolumes_ARG, 'p', "maxphysicalvolumes", int_arg, 0, 0) | ||||
| arg(permission_ARG, 'p', "permission", permission_arg, 0, 0) | ||||
| arg(partial_ARG, 'P', "partial", NULL, 0, 0) | ||||
| arg(physicalvolume_ARG, 'P', "physicalvolume", NULL, 0, 0) | ||||
| arg(quiet_ARG, 'q', "quiet", NULL, ARG_COUNTABLE, 0) | ||||
| arg(readahead_ARG, 'r', "readahead", readahead_arg, 0, 0) | ||||
| arg(resizefs_ARG, 'r', "resizefs", NULL, 0, 0) | ||||
| arg(reset_ARG, 'R', "reset", NULL, 0, 0) | ||||
| arg(regionsize_ARG, 'R', "regionsize", size_mb_arg, 0, 0) | ||||
| arg(physicalextentsize_ARG, 's', "physicalextentsize", size_mb_arg, 0, 0) | ||||
| arg(snapshot_ARG, 's', "snapshot", NULL, 0, 0) | ||||
| arg(short_ARG, 's', "short", NULL, 0, 0) | ||||
| arg(stdin_ARG, 's', "stdin", NULL, 0, 0) | ||||
| arg(select_ARG, 'S', "select", string_arg, ARG_GROUPABLE, 0) | ||||
| arg(test_ARG, 't', "test", NULL, 0, 0) | ||||
| arg(thin_ARG, 'T', "thin", NULL, 0, 0) | ||||
| arg(uuid_ARG, 'u', "uuid", NULL, 0, 0) | ||||
| arg(uuidstr_ARG, 'u', "uuid", string_arg, 0, 0) | ||||
| arg(uuidlist_ARG, 'U', "uuidlist", NULL, 0, 0) | ||||
| arg(verbose_ARG, 'v', "verbose", NULL, ARG_COUNTABLE, 0) | ||||
| arg(volumegroup_ARG, 'V', "volumegroup", NULL, 0, 0) | ||||
| arg(virtualsize_ARG, 'V', "virtualsize", size_mb_arg, 0, 0) | ||||
| arg(wipesignatures_ARG, 'W', "wipesignatures", yes_no_arg, 0, 0) | ||||
| arg(allocatable_ARG, 'x', "allocatable", yes_no_arg, 0, 0) | ||||
| arg(resizeable_ARG, 'x', "resizeable", yes_no_arg, 0, 0) | ||||
| arg(yes_ARG, 'y', "yes", NULL, 0, 0) | ||||
| arg(zero_ARG, 'Z', "zero", yes_no_arg, 0, 0) | ||||
| arg(activate_ARG, 'a', "activate", activation_VAL, 0, 0) | ||||
| arg(all_ARG, 'a', "all", 0, 0, 0) | ||||
| arg(autobackup_ARG, 'A', "autobackup", bool_VAL, 0, 0) | ||||
| arg(activevolumegroups_ARG, 'A', "activevolumegroups", 0, 0, 0) | ||||
| arg(background_ARG, 'b', "background", 0, 0, 0) | ||||
| arg(backgroundfork_ARG, 'b', "background", 0, 0, 0) | ||||
| arg(basevgname_ARG, 'n', "basevgname", string_VAL, 0, 0) | ||||
| arg(blockdevice_ARG, 'b', "blockdevice", 0, 0, 0) | ||||
| arg(chunksize_ARG, 'c', "chunksize", sizekb_VAL, 0, 0) | ||||
| arg(clustered_ARG, 'c', "clustered", bool_VAL, 0, 0) | ||||
| arg(colon_ARG, 'c', "colon", 0, 0, 0) | ||||
| arg(columns_ARG, 'C', "columns", 0, 0, 0) | ||||
| arg(contiguous_ARG, 'C', "contiguous", bool_VAL, 0, 0) | ||||
| arg(debug_ARG, 'd', "debug", 0, ARG_COUNTABLE, 0) | ||||
| arg(exported_ARG, 'e', "exported", 0, 0, 0) | ||||
| arg(physicalextent_ARG, 'E', "physicalextent", 0, 0, 0) | ||||
| arg(file_ARG, 'f', "file", string_VAL, 0, 0) | ||||
| arg(force_ARG, 'f', "force", 0, ARG_COUNTABLE, 0) | ||||
| arg(full_ARG, 'f', "full", 0, 0, 0) | ||||
| arg(help_ARG, 'h', "help", 0, ARG_COUNTABLE, 0) | ||||
| arg(cache_ARG, 'H', "cache", 0, 0, 0) | ||||
| arg(history_ARG, 'H', "history", 0, 0, 0) | ||||
| arg(help2_ARG, '?', "", 0, 0, 0) | ||||
| arg(import_ARG, 'i', "import", 0, 0, 0) | ||||
| arg(interval_ARG, 'i', "interval", number_VAL, 0, 0) | ||||
| arg(iop_version_ARG, 'i', "iop_version", 0, 0, 0) | ||||
| arg(stripes_ARG, 'i', "stripes", number_VAL, 0, 0) | ||||
| arg(stripesize_ARG, 'I', "stripesize", sizekb_VAL, 0, 0) | ||||
| arg(logicalvolume_ARG, 'l', "logicalvolume", number_VAL, 0, 0) | ||||
| arg(maxlogicalvolumes_ARG, 'l', "maxlogicalvolumes", number_VAL, 0, 0) | ||||
| arg(extents_ARG, 'l', "extents", numsignedper_VAL, 0, 0) | ||||
| arg(list_ARG, 'l', "list", 0, 0, 0) | ||||
| arg(lvmpartition_ARG, 'l', "lvmpartition", 0, 0, 0) | ||||
| arg(size_ARG, 'L', "size", sizemb_VAL, 0, 0) | ||||
| arg(persistent_ARG, 'M', "persistent", bool_VAL, 0, 0) | ||||
| arg(major_ARG, 'j', "major", number_VAL, ARG_GROUPABLE, 0) | ||||
| arg(setactivationskip_ARG, 'k', "setactivationskip", bool_VAL, 0, 0) | ||||
| arg(ignoreactivationskip_ARG, 'K', "ignoreactivationskip", 0, 0, 0) | ||||
| arg(maps_ARG, 'm', "maps", 0, 0, 0) | ||||
| arg(mirrors_ARG, 'm', "mirrors", numsigned_VAL, 0, 0) | ||||
| arg(metadatatype_ARG, 'M', "metadatatype", metadatatype_VAL, 0, 0) | ||||
| arg(name_ARG, 'n', "name", string_VAL, 0, 0) | ||||
| arg(nofsck_ARG, 'n', "nofsck", 0, 0, 0) | ||||
| arg(novolumegroup_ARG, 'n', "novolumegroup", 0, 0, 0) | ||||
| arg(oldpath_ARG, 'n', "oldpath", 0, 0, 0) | ||||
| arg(options_ARG, 'o', "options", string_VAL, ARG_GROUPABLE, 0) | ||||
| arg(sort_ARG, 'O', "sort", string_VAL, ARG_GROUPABLE, 0) | ||||
| arg(maxphysicalvolumes_ARG, 'p', "maxphysicalvolumes", number_VAL, 0, 0) | ||||
| arg(permission_ARG, 'p', "permission", permission_VAL, 0, 0) | ||||
| arg(partial_ARG, 'P', "partial", 0, 0, 0) | ||||
| arg(physicalvolume_ARG, 'P', "physicalvolume", 0, 0, 0) | ||||
| arg(quiet_ARG, 'q', "quiet", 0, ARG_COUNTABLE, 0) | ||||
| arg(readahead_ARG, 'r', "readahead", readahead_VAL, 0, 0) | ||||
| arg(resizefs_ARG, 'r', "resizefs", 0, 0, 0) | ||||
| arg(reset_ARG, 'R', "reset", 0, 0, 0) | ||||
| arg(regionsize_ARG, 'R', "regionsize", sizemb_VAL, 0, 0) | ||||
| arg(physicalextentsize_ARG, 's', "physicalextentsize", sizemb_VAL, 0, 0) | ||||
| arg(snapshot_ARG, 's', "snapshot", 0, 0, 0) | ||||
| arg(short_ARG, 's', "short", 0, 0, 0) | ||||
| arg(stdin_ARG, 's', "stdin", 0, 0, 0) | ||||
| arg(select_ARG, 'S', "select", string_VAL, ARG_GROUPABLE, 0) | ||||
| arg(test_ARG, 't', "test", 0, 0, 0) | ||||
| arg(thin_ARG, 'T', "thin", 0, 0, 0) | ||||
| arg(uuid_ARG, 'u', "uuid", 0, 0, 0) | ||||
| arg(uuidstr_ARG, 'u', "uuid", string_VAL, 0, 0) | ||||
| arg(uuidlist_ARG, 'U', "uuidlist", 0, 0, 0) | ||||
| arg(verbose_ARG, 'v', "verbose", 0, ARG_COUNTABLE, 0) | ||||
| arg(volumegroup_ARG, 'V', "volumegroup", 0, 0, 0) | ||||
| arg(virtualsize_ARG, 'V', "virtualsize", sizemb_VAL, 0, 0) | ||||
| arg(wipesignatures_ARG, 'W', "wipesignatures", bool_VAL, 0, 0) | ||||
| arg(allocatable_ARG, 'x', "allocatable", bool_VAL, 0, 0) | ||||
| arg(resizeable_ARG, 'x', "resizeable", bool_VAL, 0, 0) | ||||
| arg(yes_ARG, 'y', "yes", 0, 0, 0) | ||||
| arg(zero_ARG, 'Z', "zero", bool_VAL, 0, 0) | ||||
|  | ||||
| /* this should always be last */ | ||||
| arg(ARG_COUNT, '-', "", NULL, 0, 0) | ||||
| arg(ARG_COUNT, '-', "", 0, 0, 0) | ||||
| /* *INDENT-ON* */ | ||||
|   | ||||
							
								
								
									
										1570
									
								
								tools/command-lines.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1570
									
								
								tools/command-lines.in
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										201
									
								
								tools/command.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										201
									
								
								tools/command.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,201 @@ | ||||
| /* | ||||
|  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.   | ||||
|  * Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved. | ||||
|  * | ||||
|  * This file is part of LVM2. | ||||
|  * | ||||
|  * 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 Lesser General Public License v.2.1. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with this program; if not, write to the Free Software Foundation, | ||||
|  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||||
|  */ | ||||
|  | ||||
| #ifndef _LVM_COMMAND_H | ||||
| #define _LVM_COMMAND_H | ||||
|  | ||||
| struct cmd_context; | ||||
|  | ||||
| /* old per-command-name function */ | ||||
| typedef int (*command_fn) (struct cmd_context *cmd, int argc, char **argv); | ||||
|  | ||||
| /* new per-command-line-id functions */ | ||||
| typedef int (*command_line_fn) (struct cmd_context *cmd, int argc, char **argv); | ||||
|  | ||||
| struct command_function { | ||||
| 	int command_line_enum; | ||||
| 	command_line_fn fn; | ||||
| }; | ||||
|  | ||||
| struct command_name { | ||||
| 	const char *name; | ||||
| 	const char *desc; /* general command description from commands.h */ | ||||
| 	unsigned int flags; | ||||
|  | ||||
| 	/* union of {required,optional}_opt_args for all commands with this name */ | ||||
| 	int valid_args[ARG_COUNT]; | ||||
| 	int num_args; | ||||
| }; | ||||
|  | ||||
| /* | ||||
|  * Command defintion | ||||
|  * | ||||
|  * A command is defined in terms of a command name, | ||||
|  * required options (+args), optional options (+args), | ||||
|  * required positional args, optional positional args. | ||||
|  * | ||||
|  * A positional arg always has non-zero pos_arg.def.types. | ||||
|  * The first positional arg has pos_arg.pos of 1. | ||||
|  */ | ||||
|  | ||||
| /* arg_def flags */ | ||||
| #define ARG_DEF_FLAG_NEW                1 << 0 | ||||
| #define ARG_DEF_FLAG_MAY_REPEAT         1 << 1 | ||||
|  | ||||
| static inline int val_bit_is_set(uint64_t val_bits, int val_enum) | ||||
| { | ||||
| 	return (val_bits & (1 << val_enum)) ? 1 : 0; | ||||
| } | ||||
|  | ||||
| static inline uint64_t val_enum_to_bit(int val_enum) | ||||
| { | ||||
| 	return (1ULL << val_enum); | ||||
| } | ||||
|  | ||||
| static inline int lvp_bit_is_set(uint64_t lvp_bits, int lvp_enum) | ||||
| { | ||||
| 	return (lvp_bits & (1 << lvp_enum)) ? 1 : 0; | ||||
| } | ||||
|  | ||||
| static inline uint64_t lvp_enum_to_bit(int lvp_enum) | ||||
| { | ||||
| 	return (1ULL << lvp_enum); | ||||
| } | ||||
|  | ||||
| static inline int lvt_bit_is_set(uint64_t lvt_bits, int lvt_enum) | ||||
| { | ||||
| 	return (lvt_bits & (1 << lvt_enum)) ? 1 : 0; | ||||
| } | ||||
|  | ||||
| static inline uint64_t lvt_enum_to_bit(int lvt_enum) | ||||
| { | ||||
| 	return (1ULL << lvt_enum); | ||||
| } | ||||
|  | ||||
| /* Description a value that follows an option or exists in a position. */ | ||||
|  | ||||
| struct arg_def { | ||||
| 	uint64_t val_bits;   /* bits of x_VAL, can be multiple for pos_arg */ | ||||
| 	uint64_t lvt_bits;   /* lvt_enum_to_bit(x_LVT) for lv_VAL, can be multiple */ | ||||
| 	uint64_t num;        /* a literal number for conststr_VAL */ | ||||
| 	const char *str;     /* a literal string for constnum_VAL */ | ||||
| 	uint32_t flags;      /* ARG_DEF_FLAG_ */ | ||||
| }; | ||||
|  | ||||
| /* Description of an option and the value that follows it. */ | ||||
|  | ||||
| struct opt_arg { | ||||
| 	int opt;             /* option, e.g. foo_ARG */ | ||||
| 	struct arg_def def;  /* defines accepted values */ | ||||
| }; | ||||
|  | ||||
| /* Description of a position and the value that exists there. */ | ||||
|  | ||||
| struct pos_arg { | ||||
| 	int pos;             /* position, e.g. first is 1 */ | ||||
| 	struct arg_def def;  /* defines accepted values */ | ||||
| }; | ||||
|  | ||||
| /* | ||||
|  * | ||||
|  * Commands using a given command definition must follow a set | ||||
|  * of rules.  If a given command+LV matches the conditions in | ||||
|  * opts/lvt_bits/lvp_bits, then the checks are applied. | ||||
|  * If one condition is not met, the checks are not applied. | ||||
|  * If no conditions are set, the checks are always applied. | ||||
|  */ | ||||
|  | ||||
| #define RULE_INVALID 1 | ||||
| #define RULE_REQUIRE 2 | ||||
|  | ||||
| struct cmd_rule { | ||||
| 	int *opts;			/* if any option in this list is set, the check may apply */ | ||||
| 	uint64_t lvt_bits;		/* if LV has one of these types (lvt_enum_to_bit), the check may apply */ | ||||
| 	uint64_t lvp_bits;		/* if LV has all of these properties (lvp_enum_to_bit), the check may apply */ | ||||
|  | ||||
| 	int *check_opts;		/* used options must [not] be in this list */ | ||||
| 	uint64_t check_lvt_bits;	/* LV must [not] have one of these type */ | ||||
| 	uint64_t check_lvp_bits;	/* LV must [not] have all of these properties */ | ||||
|  | ||||
| 	uint32_t rule;			/* RULE_INVALID, RULE_REQUIRE: check values must [not] be true */ | ||||
| 	int opts_count;			/* entries in opts[] */ | ||||
| 	int check_opts_count;		/* entries in check_opts[] */ | ||||
|  | ||||
| }; | ||||
|  | ||||
| /* | ||||
|  * CMD_RO_ARGS needs to accomodate a list of options, | ||||
|  * of which one is required after which the rest are | ||||
|  * optional. | ||||
|  */ | ||||
| #define CMD_RO_ARGS 64          /* required opt args */ | ||||
| #define CMD_OO_ARGS 150         /* optional opt args */ | ||||
| #define CMD_RP_ARGS 8           /* required positional args */ | ||||
| #define CMD_OP_ARGS 8           /* optional positional args */ | ||||
| #define CMD_MAX_RULES 32        /* max number of rules per command def */ | ||||
|  | ||||
| /* | ||||
|  * one or more from required_opt_args is required, | ||||
|  * then the rest are optional. | ||||
|  */ | ||||
| #define CMD_FLAG_ONE_REQUIRED_OPT   1 | ||||
| #define CMD_FLAG_SECONDARY_SYNTAX   2 | ||||
|  | ||||
| /* a register of the lvm commands */ | ||||
| struct command { | ||||
| 	const char *name; | ||||
| 	const char *desc; /* specific command description from command-lines.h */ | ||||
| 	const char *usage; /* excludes common options like --help, --debug */ | ||||
| 	const char *usage_common; /* includes commmon options like --help, --debug */ | ||||
| 	const char *command_line_id; | ||||
| 	int command_line_enum; /* <command_line_id>_CMD */ | ||||
|  | ||||
| 	struct command_name *cname; | ||||
|  | ||||
| 	command_fn fn;                      /* old style */ | ||||
| 	struct command_function *functions; /* new style */ | ||||
|  | ||||
| 	unsigned int flags; /* copied from command_name.flags from commands.h */ | ||||
|  | ||||
| 	unsigned int cmd_flags; /* CMD_FLAG_ */ | ||||
|  | ||||
| 	/* definitions of opt/pos args */ | ||||
|  | ||||
| 	/* required args following an --opt */ | ||||
| 	struct opt_arg required_opt_args[CMD_RO_ARGS]; | ||||
|  | ||||
| 	/* optional args following an --opt */ | ||||
| 	struct opt_arg optional_opt_args[CMD_OO_ARGS]; | ||||
|  | ||||
| 	/* required positional args */ | ||||
| 	struct pos_arg required_pos_args[CMD_RP_ARGS]; | ||||
|  | ||||
| 	/* optional positional args */ | ||||
| 	struct pos_arg optional_pos_args[CMD_OP_ARGS]; | ||||
|  | ||||
| 	struct cmd_rule rules[CMD_MAX_RULES]; | ||||
|  | ||||
| 	int ro_count; | ||||
| 	int oo_count; | ||||
| 	int rp_count; | ||||
| 	int op_count; | ||||
|  | ||||
| 	/* used for processing current position */ | ||||
| 	int pos_count; | ||||
|  | ||||
| 	int rule_count; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										1428
									
								
								tools/commands.h
									
									
									
									
									
								
							
							
						
						
									
										1428
									
								
								tools/commands.h
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										2898
									
								
								tools/create-commands.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2898
									
								
								tools/create-commands.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										56
									
								
								tools/lv_props.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								tools/lv_props.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
|  | ||||
| /* | ||||
|  * NULL in the last arg can be replaced with actual | ||||
|  * calls to the lv_is_prop() function when those | ||||
|  * become functions (are #define now), take uniform | ||||
|  * args (e.g. some take cmd others don't), and are | ||||
|  * exposed in tools.h | ||||
|  * | ||||
|  * Until then, the lv_is_prop() functions are | ||||
|  * called indirectly through _lv_is_prop(). | ||||
|  */ | ||||
|  | ||||
| lvp(LVP_NONE, "", NULL) /* enum value 0 means none */ | ||||
| lvp(is_locked_LVP, "lv_is_locked", NULL) | ||||
| lvp(is_partial_LVP, "lv_is_partial", NULL) | ||||
| lvp(is_virtual_LVP, "lv_is_virtual", NULL) | ||||
| lvp(is_merging_LVP, "lv_is_merging", NULL) | ||||
| lvp(is_merging_origin_LVP, "lv_is_merging_origin", NULL) | ||||
| lvp(is_converting_LVP, "lv_is_converting", NULL) | ||||
| lvp(is_external_origin_LVP, "lv_is_external_origin", NULL) | ||||
| lvp(is_virtual_origin_LVP, "lv_is_virtual_origin", NULL) | ||||
| lvp(is_not_synced_LVP, "lv_is_not_synced", NULL) | ||||
| lvp(is_pending_delete_LVP, "lv_is_pending_delete", NULL) | ||||
| lvp(is_error_when_full_LVP, "lv_is_error_when_full", NULL) | ||||
| lvp(is_pvmove_LVP, "lv_is_pvmove", NULL) | ||||
| lvp(is_removed_LVP, "lv_is_removed", NULL) | ||||
| lvp(is_vg_writable_LVP, "lv_is_vg_writable", NULL) | ||||
|  | ||||
| /* kinds of sub LV */ | ||||
| lvp(is_thinpool_data_LVP, "lv_is_thinpool_data", NULL) | ||||
| lvp(is_thinpool_metadata_LVP, "lv_is_thinpool_metadata", NULL) | ||||
| lvp(is_cachepool_data_LVP, "lv_is_cachepool_data", NULL) | ||||
| lvp(is_cachepool_metadata_LVP, "lv_is_cachepool_metadata", NULL) | ||||
| lvp(is_mirror_image_LVP, "lv_is_mirror_image", NULL) | ||||
| lvp(is_mirror_log_LVP, "lv_is_mirror_log", NULL) | ||||
| lvp(is_raid_image_LVP, "lv_is_raid_image", NULL) | ||||
| lvp(is_raid_metadata_LVP, "lv_is_raid_metadata", NULL) | ||||
|  | ||||
| /* | ||||
|  * is_thick_origin should be used instead of is_origin | ||||
|  * is_thick_snapshot is generally used as LV_snapshot from lv_types.h | ||||
|  */ | ||||
| lvp(is_origin_LVP, "lv_is_origin", NULL) | ||||
| lvp(is_thick_origin_LVP, "lv_is_thick_origin", NULL) | ||||
| lvp(is_thick_snapshot_LVP, "lv_is_thick_snapshot", NULL) | ||||
| lvp(is_thin_origin_LVP, "lv_is_thin_origin", NULL) | ||||
| lvp(is_thin_snapshot_LVP, "lv_is_thin_snapshot", NULL) | ||||
|  | ||||
| lvp(is_cache_origin_LVP, "lv_is_cache_origin", NULL) | ||||
| lvp(is_merging_cow_LVP, "lv_is_merging_cow", NULL) | ||||
| lvp(is_cow_covering_origin_LVP, "lv_is_cow_covering_origin", NULL) | ||||
| lvp(is_visible_LVP, "lv_is_visible", NULL) | ||||
| lvp(is_historical_LVP, "lv_is_historical", NULL) | ||||
| lvp(is_raid_with_tracking_LVP, "lv_is_raid_with_tracking", NULL) | ||||
| lvp(LVP_COUNT, "", NULL) | ||||
|  | ||||
							
								
								
									
										32
									
								
								tools/lv_types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								tools/lv_types.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * LV types used in command definitions.  The type strings are used | ||||
|  * as LV suffixes, e.g. LV_type or LV_type1_type2. | ||||
|  * | ||||
|  * The final NULL arg can be replaced with lv_is_type() functions | ||||
|  * if the current lv_is_type #defines become functions and are | ||||
|  * moved to tools.h | ||||
|  * | ||||
|  * Until then, the lv_is_type() functions are called indirectly | ||||
|  * through _lv_is_type(). | ||||
|  */ | ||||
|  | ||||
| lvt(LVT_NONE, "", NULL) | ||||
| lvt(linear_LVT, "linear", NULL) | ||||
| lvt(striped_LVT, "striped", NULL) | ||||
| lvt(snapshot_LVT, "snapshot", NULL) /* lv_is_cow, lv_is_thick_snapshot */ | ||||
| lvt(thin_LVT, "thin", NULL) | ||||
| lvt(thinpool_LVT, "thinpool", NULL) | ||||
| lvt(cache_LVT, "cache", NULL) | ||||
| lvt(cachepool_LVT, "cachepool", NULL) | ||||
| lvt(mirror_LVT, "mirror", NULL) | ||||
| lvt(raid_LVT, "raid", NULL) | ||||
| lvt(raid0_LVT, "raid0", NULL) | ||||
| lvt(raid1_LVT, "raid1", NULL) | ||||
| lvt(raid4_LVT, "raid4", NULL) | ||||
| lvt(raid5_LVT, "raid5", NULL) | ||||
| lvt(raid6_LVT, "raid6", NULL) | ||||
| lvt(raid10_LVT, "raid10", NULL) | ||||
| lvt(LVT_COUNT, "", NULL) | ||||
|  | ||||
							
								
								
									
										32
									
								
								tools/lvm.c
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								tools/lvm.c
									
									
									
									
									
								
							| @@ -45,9 +45,9 @@ static char *_list_cmds(const char *text, int state) | ||||
| 		len = strlen(text); | ||||
| 	} | ||||
|  | ||||
| 	while (i < _cmdline->num_commands) | ||||
| 		if (!strncmp(text, _cmdline->commands[i++].name, len)) | ||||
| 			return strdup(_cmdline->commands[i - 1].name); | ||||
| 	while (i < _cmdline->num_command_names) | ||||
| 		if (!strncmp(text, _cmdline->command_names[i++].name, len)) | ||||
| 			return strdup(_cmdline->command_names[i - 1].name); | ||||
|  | ||||
| 	return NULL; | ||||
| } | ||||
| @@ -57,7 +57,7 @@ static char *_list_args(const char *text, int state) | ||||
| { | ||||
| 	static int match_no = 0; | ||||
| 	static size_t len = 0; | ||||
| 	static struct command *com; | ||||
| 	static struct command_name *cname; | ||||
|  | ||||
| 	/* Initialise if this is a new completion attempt */ | ||||
| 	if (!state) { | ||||
| @@ -65,40 +65,40 @@ static char *_list_args(const char *text, int state) | ||||
| 		int j; | ||||
|  | ||||
| 		match_no = 0; | ||||
| 		com = NULL; | ||||
| 		cname = NULL; | ||||
| 		len = strlen(text); | ||||
|  | ||||
| 		/* Find start of first word in line buffer */ | ||||
| 		while (isspace(*s)) | ||||
| 			s++; | ||||
|  | ||||
| 		/* Look for word in list of commands */ | ||||
| 		for (j = 0; j < _cmdline->num_commands; j++) { | ||||
| 		/* Look for word in list of command names */ | ||||
| 		for (j = 0; j < _cmdline->num_command_names; j++) { | ||||
| 			const char *p; | ||||
| 			char *q = s; | ||||
|  | ||||
| 			p = _cmdline->commands[j].name; | ||||
| 			p = _cmdline->command_names[j].name; | ||||
| 			while (*p == *q) { | ||||
| 				p++; | ||||
| 				q++; | ||||
| 			} | ||||
| 			if ((!*p) && *q == ' ') { | ||||
| 				com = _cmdline->commands + j; | ||||
| 				cname = _cmdline->command_names + j; | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (!com) | ||||
| 	if (!cname) | ||||
| 		return NULL; | ||||
|  | ||||
| 	/* Short form arguments */ | ||||
| 	if (len < 3) { | ||||
| 		while (match_no < com->num_args) { | ||||
| 		while (match_no < cname->num_args) { | ||||
| 			char s[3]; | ||||
| 			char c; | ||||
| 			if (!(c = (_cmdline->arg_props + | ||||
| 				   com->valid_args[match_no++])->short_arg)) | ||||
| 				   cname->valid_args[match_no++])->short_arg)) | ||||
| 				continue; | ||||
|  | ||||
| 			sprintf(s, "-%c", c); | ||||
| @@ -108,13 +108,13 @@ static char *_list_args(const char *text, int state) | ||||
| 	} | ||||
|  | ||||
| 	/* Long form arguments */ | ||||
| 	if (match_no < com->num_args) | ||||
| 		match_no = com->num_args; | ||||
| 	if (match_no < cname->num_args) | ||||
| 		match_no = cname->num_args; | ||||
|  | ||||
| 	while (match_no - com->num_args < com->num_args) { | ||||
| 	while (match_no - cname->num_args < cname->num_args) { | ||||
| 		const char *l; | ||||
| 		l = (_cmdline->arg_props + | ||||
| 		     com->valid_args[match_no++ - com->num_args])->long_arg; | ||||
| 		     cname->valid_args[match_no++ - cname->num_args])->long_arg; | ||||
| 		if (*(l + 2) && !strncmp(text, l, len)) | ||||
| 			return strdup(l); | ||||
| 	} | ||||
|   | ||||
| @@ -19,10 +19,11 @@ | ||||
| struct cmd_context; | ||||
|  | ||||
| struct cmdline_context { | ||||
|         struct arg_props *arg_props; | ||||
|         struct command *commands; | ||||
|         int num_commands; | ||||
|         int commands_size; | ||||
| 	struct arg_props *arg_props; | ||||
| 	struct command *commands; | ||||
| 	int num_commands; | ||||
| 	struct command_name *command_names; | ||||
| 	int num_command_names; | ||||
| }; | ||||
|  | ||||
| int lvm2_main(int argc, char **argv); | ||||
|   | ||||
| @@ -30,12 +30,12 @@ void *cmdlib_lvm2_init(unsigned static_compile) | ||||
| { | ||||
| 	struct cmd_context *cmd; | ||||
|  | ||||
| 	lvm_register_commands(); | ||||
|  | ||||
| 	init_is_static(static_compile); | ||||
| 	if (!(cmd = init_lvm(1, 1))) | ||||
| 		return NULL; | ||||
|  | ||||
| 	lvm_register_commands(); | ||||
|  | ||||
| 	return (void *) cmd; | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										1440
									
								
								tools/lvmcmdline.c
									
									
									
									
									
								
							
							
						
						
									
										1440
									
								
								tools/lvmcmdline.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										587
									
								
								tools/toollib.c
									
									
									
									
									
								
							
							
						
						
									
										587
									
								
								tools/toollib.c
									
									
									
									
									
								
							| @@ -801,10 +801,7 @@ int vgcreate_params_set_from_args(struct cmd_context *cmd, | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	if (arg_is_set(cmd, metadatacopies_ARG)) | ||||
| 		vp_new->vgmetadatacopies = arg_int_value(cmd, metadatacopies_ARG, | ||||
| 							DEFAULT_VGMETADATACOPIES); | ||||
| 	else if (arg_is_set(cmd, vgmetadatacopies_ARG)) | ||||
| 	if (arg_is_set(cmd, vgmetadatacopies_ARG)) | ||||
| 		vp_new->vgmetadatacopies = arg_int_value(cmd, vgmetadatacopies_ARG, | ||||
| 							DEFAULT_VGMETADATACOPIES); | ||||
| 	else | ||||
| @@ -2329,6 +2326,541 @@ static struct lv_segment _historical_lv_segment = { | ||||
| 	.origin_list = DM_LIST_HEAD_INIT(_historical_lv_segment.origin_list), | ||||
| }; | ||||
|  | ||||
| int opt_in_list_is_set(struct cmd_context *cmd, int *opts, int count, | ||||
| 		       int *match_count, int *unmatch_count) | ||||
| { | ||||
| 	int match = 0; | ||||
| 	int unmatch = 0; | ||||
| 	int i; | ||||
|  | ||||
| 	for (i = 0; i < count; i++) { | ||||
| 		if (arg_is_set(cmd, opts[i])) | ||||
| 			match++; | ||||
| 		else | ||||
| 			unmatch++; | ||||
| 	} | ||||
|  | ||||
| 	if (match_count) | ||||
| 		*match_count = match; | ||||
| 	if (unmatch_count) | ||||
| 		*unmatch_count = unmatch; | ||||
|  | ||||
| 	return match ? 1 : 0; | ||||
| } | ||||
|        | ||||
| void opt_array_to_str(struct cmd_context *cmd, int *opts, int count, | ||||
| 		      char *buf, int len) | ||||
| { | ||||
| 	int pos = 0; | ||||
| 	int ret; | ||||
| 	int i; | ||||
|  | ||||
| 	for (i = 0; i < count; i++) { | ||||
| 		ret = snprintf(buf + pos, len - pos, "%s ", arg_long_option_name(opts[i])); | ||||
| 		if (ret >= len - pos) | ||||
| 			break; | ||||
| 		pos += ret; | ||||
| 	} | ||||
|  | ||||
| 	buf[len - 1] = '\0'; | ||||
| } | ||||
|  | ||||
| static void lvp_bits_to_str(uint64_t bits, char *buf, int len) | ||||
| { | ||||
| 	struct lv_props *prop; | ||||
| 	int lvp_enum; | ||||
| 	int pos = 0; | ||||
| 	int ret; | ||||
|  | ||||
| 	for (lvp_enum = 0; lvp_enum < LVP_COUNT; lvp_enum++) { | ||||
| 		if (!(prop = get_lv_prop(lvp_enum))) | ||||
| 			continue; | ||||
|  | ||||
| 		if (lvp_bit_is_set(bits, lvp_enum)) { | ||||
| 			ret = snprintf(buf + pos, len - pos, "%s ", prop->name); | ||||
| 			if (ret >= len - pos) | ||||
| 				break; | ||||
| 			pos += ret; | ||||
| 		} | ||||
| 	} | ||||
| 	buf[len - 1] = '\0'; | ||||
| } | ||||
|  | ||||
| static void lvt_bits_to_str(uint64_t bits, char *buf, int len) | ||||
| { | ||||
| 	struct lv_types *type; | ||||
| 	int lvt_enum; | ||||
| 	int pos = 0; | ||||
| 	int ret; | ||||
|  | ||||
| 	for (lvt_enum = 0; lvt_enum < LVT_COUNT; lvt_enum++) { | ||||
| 		if (!(type = get_lv_type(lvt_enum))) | ||||
| 			continue; | ||||
|  | ||||
| 		if (lvt_bit_is_set(bits, lvt_enum)) { | ||||
| 			ret = snprintf(buf + pos, len - pos, "%s ", type->name); | ||||
| 			if (ret >= len - pos) | ||||
| 				break; | ||||
| 			pos += ret; | ||||
| 		} | ||||
| 	} | ||||
| 	buf[len - 1] = '\0'; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * This is the lv_prop function pointer used for lv_is_foo() #defines. | ||||
|  * Alternatively, lv_is_foo() could all be turned into functions. | ||||
|  */ | ||||
|  | ||||
| static int _lv_is_prop(struct cmd_context *cmd, struct logical_volume *lv, int lvp_enum) | ||||
| { | ||||
| 	switch (lvp_enum) { | ||||
| 	case is_locked_LVP: | ||||
| 		return lv_is_locked(lv); | ||||
| 	case is_partial_LVP: | ||||
| 		return lv_is_partial(lv); | ||||
| 	case is_virtual_LVP: | ||||
| 		return lv_is_virtual(lv); | ||||
| 	case is_merging_LVP: | ||||
| 		return lv_is_merging(lv); | ||||
| 	case is_merging_origin_LVP: | ||||
| 		return lv_is_merging_origin(lv); | ||||
| 	case is_converting_LVP: | ||||
| 		return lv_is_converting(lv); | ||||
| 	case is_external_origin_LVP: | ||||
| 		return lv_is_external_origin(lv); | ||||
| 	case is_virtual_origin_LVP: | ||||
| 		return lv_is_virtual_origin(lv); | ||||
| 	case is_not_synced_LVP: | ||||
| 		return lv_is_not_synced(lv); | ||||
| 	case is_pending_delete_LVP: | ||||
| 		return lv_is_pending_delete(lv); | ||||
| 	case is_error_when_full_LVP: | ||||
| 		return lv_is_error_when_full(lv); | ||||
| 	case is_pvmove_LVP: | ||||
| 		return lv_is_pvmove(lv); | ||||
| 	case is_removed_LVP: | ||||
| 		return lv_is_removed(lv); | ||||
| 	case is_vg_writable_LVP: | ||||
| 		return (lv->vg->status & LVM_WRITE) ? 1 : 0; | ||||
| 	case is_thinpool_data_LVP: | ||||
| 		return lv_is_thin_pool_data(lv); | ||||
| 	case is_thinpool_metadata_LVP: | ||||
| 		return lv_is_thin_pool_metadata(lv); | ||||
| 	case is_cachepool_data_LVP: | ||||
| 		return lv_is_cache_pool_data(lv); | ||||
| 	case is_cachepool_metadata_LVP: | ||||
| 		return lv_is_cache_pool_metadata(lv); | ||||
| 	case is_mirror_image_LVP: | ||||
| 		return lv_is_mirror_image(lv); | ||||
| 	case is_mirror_log_LVP: | ||||
| 		return lv_is_mirror_log(lv); | ||||
| 	case is_raid_image_LVP: | ||||
| 		return lv_is_raid_image(lv); | ||||
| 	case is_raid_metadata_LVP: | ||||
| 		return lv_is_raid_metadata(lv); | ||||
| 	case is_origin_LVP: /* use lv_is_thick_origin */ | ||||
| 		return lv_is_origin(lv); | ||||
| 	case is_thick_origin_LVP: | ||||
| 		return lv_is_thick_origin(lv); | ||||
| 	case is_thick_snapshot_LVP: | ||||
| 		return lv_is_thick_snapshot(lv); | ||||
| 	case is_thin_origin_LVP: | ||||
| 		return lv_is_thin_origin(lv, NULL); | ||||
| 	case is_thin_snapshot_LVP: | ||||
| 		return lv_is_thin_snapshot(lv); | ||||
| 	case is_cache_origin_LVP: | ||||
| 		return lv_is_cache_origin(lv); | ||||
| 	case is_merging_cow_LVP: | ||||
| 		return lv_is_merging_cow(lv); | ||||
| 	case is_cow_covering_origin_LVP: | ||||
| 		return lv_is_cow_covering_origin(lv); | ||||
| 	case is_visible_LVP: | ||||
| 		return lv_is_visible(lv); | ||||
| 	case is_historical_LVP: | ||||
| 		return lv_is_historical(lv); | ||||
| 	case is_raid_with_tracking_LVP: | ||||
| 		return lv_is_raid_with_tracking(lv); | ||||
| 	default: | ||||
| 		log_error(INTERNAL_ERROR "unknown lv property value lvp_enum %d", lvp_enum); | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Check if an LV matches a given LV type enum. | ||||
|  */ | ||||
|  | ||||
| static int _lv_is_type(struct cmd_context *cmd, struct logical_volume *lv, int lvt_enum) | ||||
| { | ||||
| 	struct lv_segment *seg = first_seg(lv); | ||||
|  | ||||
| 	switch (lvt_enum) { | ||||
| 	case striped_LVT: | ||||
| 		return seg_is_striped(seg); | ||||
| 	case linear_LVT: | ||||
| 		return seg_is_linear(seg); | ||||
| 	case snapshot_LVT: | ||||
| 		return lv_is_cow(lv); | ||||
| 	case thin_LVT: | ||||
| 		return lv_is_thin_volume(lv); | ||||
| 	case thinpool_LVT: | ||||
| 		return lv_is_thin_pool(lv); | ||||
| 	case cache_LVT: | ||||
| 		return lv_is_cache(lv); | ||||
| 	case cachepool_LVT: | ||||
| 		return lv_is_cache_pool(lv); | ||||
| 	case mirror_LVT: | ||||
| 		return lv_is_mirror(lv); | ||||
| 	case raid_LVT: | ||||
| 		return lv_is_raid(lv); | ||||
| 	case raid0_LVT: | ||||
| 		return seg_is_raid0(seg); | ||||
| 	case raid1_LVT: | ||||
| 		return seg_is_raid1(seg); | ||||
| 	case raid4_LVT: | ||||
| 		return seg_is_raid4(seg); | ||||
| #if 0 | ||||
| 	case raid5_LVT: | ||||
| 		return seg_is_raid5(seg); | ||||
| 	case raid6_LVT: | ||||
| 		return seg_is_raid6(seg); | ||||
| #endif | ||||
| 	case raid10_LVT: | ||||
| 		return seg_is_raid10(seg); | ||||
| 	default: | ||||
| 		log_error(INTERNAL_ERROR "unknown lv type value lvt_enum %d", lvt_enum); | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int _get_lvt_enum(struct logical_volume *lv) | ||||
| { | ||||
| 	struct lv_segment *seg = first_seg(lv); | ||||
|  | ||||
| 	if (seg_is_striped(seg)) | ||||
| 		return striped_LVT; | ||||
| 	if (seg_is_linear(seg)) | ||||
| 		return linear_LVT; | ||||
| 	if (lv_is_cow(lv)) | ||||
| 		return snapshot_LVT; | ||||
| 	if (lv_is_thin_volume(lv)) | ||||
| 		return thin_LVT; | ||||
| 	if (lv_is_thin_pool(lv)) | ||||
| 		return thinpool_LVT; | ||||
| 	if (lv_is_cache(lv)) | ||||
| 		return cache_LVT; | ||||
| 	if (lv_is_cache_pool(lv)) | ||||
| 		return cachepool_LVT; | ||||
| 	if (lv_is_mirror(lv)) | ||||
| 		return mirror_LVT; | ||||
| 	if (lv_is_raid(lv)) | ||||
| 		return raid_LVT; | ||||
| 	if (seg_is_raid0(seg)) | ||||
| 		return raid0_LVT; | ||||
| 	if (seg_is_raid1(seg)) | ||||
| 		return raid1_LVT; | ||||
| 	if (seg_is_raid4(seg)) | ||||
| 		return raid4_LVT; | ||||
| #if 0 | ||||
| 	if (seg_is_raid5(seg)) | ||||
| 		return raid5_LVT; | ||||
| 	if (seg_is_raid6(seg)) | ||||
| 		return raid6_LVT; | ||||
| #endif | ||||
| 	if (seg_is_raid10(seg)) | ||||
| 		return raid10_LVT; | ||||
|  | ||||
| 	log_error(INTERNAL_ERROR "unknown lv type for %s", display_lvname(lv)); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Call lv_is_<type> for each <type>_LVT bit set in lvt_bits. | ||||
|  * If lv matches one of the specified lv types, then return 1. | ||||
|  */ | ||||
|  | ||||
| static int _lv_types_match(struct cmd_context *cmd, struct logical_volume *lv, uint64_t lvt_bits, | ||||
| 			   uint64_t *match_bits, uint64_t *unmatch_bits) | ||||
| { | ||||
| 	struct lv_types *type; | ||||
| 	int lvt_enum; | ||||
| 	int found_a_match = 0; | ||||
| 	int match; | ||||
|  | ||||
| 	if (match_bits) | ||||
| 		*match_bits = 0; | ||||
| 	if (unmatch_bits) | ||||
| 		*unmatch_bits = 0; | ||||
|  | ||||
| 	for (lvt_enum = 1; lvt_enum < LVT_COUNT; lvt_enum++) { | ||||
| 		if (!lvt_bit_is_set(lvt_bits, lvt_enum)) | ||||
| 			continue; | ||||
|  | ||||
| 		if (!(type = get_lv_type(lvt_enum))) | ||||
| 			continue; | ||||
|  | ||||
| 		/* | ||||
| 		 * All types are currently handled by _lv_is_type() | ||||
| 		 * because lv_is_type() are #defines and not exposed | ||||
| 		 * in tools.h | ||||
| 		 */ | ||||
|  | ||||
| 		if (!type->fn) | ||||
| 			match = _lv_is_type(cmd, lv, lvt_enum); | ||||
| 		else | ||||
| 			match = type->fn(cmd, lv); | ||||
|  | ||||
| 		if (match) | ||||
| 			found_a_match = 1; | ||||
|  | ||||
| 		if (match_bits && match) | ||||
| 			*match_bits |= lvt_enum_to_bit(lvt_enum); | ||||
|  | ||||
| 		if (unmatch_bits && !match) | ||||
| 			*unmatch_bits |= lvt_enum_to_bit(lvt_enum); | ||||
| 	} | ||||
|  | ||||
| 	return found_a_match; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Call lv_is_<prop> for each <prop>_LVP bit set in lvp_bits. | ||||
|  * If lv matches all of the specified lv properties, then return 1. | ||||
|  */ | ||||
|  | ||||
| static int _lv_props_match(struct cmd_context *cmd, struct logical_volume *lv, uint64_t lvp_bits, | ||||
| 			   uint64_t *match_bits, uint64_t *unmatch_bits) | ||||
| { | ||||
| 	struct lv_props *prop; | ||||
| 	int lvp_enum; | ||||
| 	int found_a_mismatch = 0; | ||||
| 	int match; | ||||
|  | ||||
| 	if (match_bits) | ||||
| 		*match_bits = 0; | ||||
| 	if (unmatch_bits) | ||||
| 		*unmatch_bits = 0; | ||||
|  | ||||
| 	for (lvp_enum = 1; lvp_enum < LVP_COUNT; lvp_enum++) { | ||||
| 		if (!lvp_bit_is_set(lvp_bits, lvp_enum)) | ||||
| 			continue; | ||||
|  | ||||
| 		if (!(prop = get_lv_prop(lvp_enum))) | ||||
| 			continue; | ||||
|  | ||||
| 		if (!prop->fn) | ||||
| 			match = _lv_is_prop(cmd, lv, lvp_enum); | ||||
| 		else | ||||
| 			match = prop->fn(cmd, lv); | ||||
|  | ||||
| 		if (!match) | ||||
| 			found_a_mismatch = 1; | ||||
|  | ||||
| 		if (match_bits && match) | ||||
| 			*match_bits |= lvp_enum_to_bit(lvp_enum); | ||||
|  | ||||
| 		if (unmatch_bits && !match) | ||||
| 			*unmatch_bits |= lvp_enum_to_bit(lvp_enum); | ||||
| 	} | ||||
|  | ||||
| 	return !found_a_mismatch; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * If the command definition specifies one required positional | ||||
|  * LV (possibly repeatable), and specifies accepted LV types, | ||||
|  * then verify that the LV being processed matches one of those | ||||
|  * types. | ||||
|  * | ||||
|  * process_each_lv() can only be used for commands that have | ||||
|  * one positional LV arg (optionally repeating, where each is | ||||
|  * processed independently.)  It cannot work for commands that | ||||
|  * have different required LVs in designated positions, like | ||||
|  * 'lvrename LV1 LV2', where each LV is not processed | ||||
|  * independently.  That means that this LV type check only | ||||
|  * needs to check the lv_type of the first positional arg. | ||||
|  */ | ||||
|  | ||||
| static int _check_lv_types(struct cmd_context *cmd, struct logical_volume *lv) | ||||
| { | ||||
| 	int ret = 1; | ||||
|  | ||||
| 	if ((cmd->command->rp_count == 1) && | ||||
| 	    val_bit_is_set(cmd->command->required_pos_args[0].def.val_bits, lv_VAL) && | ||||
| 	    cmd->command->required_pos_args[0].def.lvt_bits) { | ||||
| 		ret = _lv_types_match(cmd, lv, cmd->command->required_pos_args[0].def.lvt_bits, NULL, NULL); | ||||
| 		if (!ret) { | ||||
| 			int lvt_enum = _get_lvt_enum(lv); | ||||
| 			struct lv_types *type = get_lv_type(lvt_enum); | ||||
| 			log_warn("Operation on LV %s which has invalid type %s.", | ||||
| 				 display_lvname(lv), type ? type->name : "unknown"); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| /* Check if LV passes each rule specified in command definition. */ | ||||
|  | ||||
| static int _check_lv_rules(struct cmd_context *cmd, struct logical_volume *lv) | ||||
| { | ||||
| 	char buf[64]; | ||||
| 	struct cmd_rule *rule; | ||||
| 	struct lv_types *lvtype = NULL; | ||||
| 	uint64_t lv_props_match_bits, lv_props_unmatch_bits; | ||||
| 	uint64_t lv_types_match_bits, lv_types_unmatch_bits; | ||||
| 	int opts_match_count, opts_unmatch_count; | ||||
| 	int lvt_enum; | ||||
| 	int ret = 1; | ||||
| 	int i; | ||||
|  | ||||
| 	lvt_enum = _get_lvt_enum(lv); | ||||
| 	if (lvt_enum) | ||||
| 		lvtype = get_lv_type(lvt_enum); | ||||
|  | ||||
| 	for (i = 0; i < cmd->command->rule_count; i++) { | ||||
| 		rule = &cmd->command->rules[i]; | ||||
|  | ||||
| 		/* | ||||
| 		 * RULE: <conditions> INVALID|REQUIRE <checks> | ||||
| 		 * | ||||
| 		 * If all the conditions apply to the command+LV, then | ||||
| 		 * the checks are performed.  If all conditions are zero | ||||
| 		 * (!opts_count, !lvt_bits, !lvp_bits), then the check | ||||
| 		 * is always performed. | ||||
| 		 * | ||||
| 		 * Conditions: | ||||
| 		 * | ||||
| 		 * 1. options (opts): if any of the specified options are set, | ||||
| 		 *    then the checks may apply. | ||||
| 		 * | ||||
| 		 * 2. LV types (lvt_bits): if any of the specified LV types | ||||
| 		 *    match the LV, then the checks may apply. | ||||
| 		 * | ||||
| 		 * 3. LV properties (lvp_bits): if all of the specified | ||||
| 		 *    LV properties match the LV, then the checks may apply. | ||||
| 		 * | ||||
| 		 * If conditions 1, 2, 3 all pass, then the checks apply. | ||||
| 		 * | ||||
| 		 * Checks: | ||||
| 		 * | ||||
| 		 * 1. options (check_opts): | ||||
| 		 *    INVALID: if any of the specified options are set, | ||||
| 		 *    then the command fails. | ||||
| 		 *    REQUIRE: if any of the specified options are not set, | ||||
| 		 *    then the command fails. | ||||
| 		 * | ||||
| 		 * 2. LV types (check_lvt_bits): | ||||
| 		 *    INVALID: if any of the specified LV types match the LV, | ||||
| 		 *    then the command fails. | ||||
| 		 *    REQUIRE: if none of the specified LV types match the LV, | ||||
| 		 *    then the command fails. | ||||
| 		 * | ||||
| 		 * 3. LV properties (check_lvp_bits): | ||||
| 		 *    INVALID: if any of the specified LV properties match | ||||
| 		 *    the LV, then the command fails. | ||||
| 		 *    REQUIRE: if any of the specified LV properties do not match | ||||
| 		 *    the LV, then the command fails. | ||||
| 		 */ | ||||
|  | ||||
| 		if (rule->opts_count && !opt_in_list_is_set(cmd, rule->opts, rule->opts_count, NULL, NULL)) | ||||
| 			continue; | ||||
|  | ||||
| 		/* If LV matches one type in lvt_bits, this returns 1. */ | ||||
| 		if (rule->lvt_bits && !_lv_types_match(cmd, lv, rule->lvt_bits, NULL, NULL)) | ||||
| 			continue; | ||||
|  | ||||
| 		/* If LV matches all properties in lvp_bits, this returns 1. */ | ||||
| 		if (rule->lvp_bits && !_lv_props_match(cmd, lv, rule->lvp_bits, NULL, NULL)) | ||||
| 			continue; | ||||
|  | ||||
| 		/* | ||||
| 		 * Check the options, LV types, LV properties. | ||||
| 		 */ | ||||
|  | ||||
| 		if (rule->check_opts) | ||||
| 			opt_in_list_is_set(cmd, rule->check_opts, rule->check_opts_count, | ||||
| 					   &opts_match_count, &opts_unmatch_count); | ||||
|  | ||||
| 		if (rule->check_lvt_bits) | ||||
| 			_lv_types_match(cmd, lv, rule->check_lvt_bits, | ||||
| 					&lv_types_match_bits, &lv_types_unmatch_bits); | ||||
|  | ||||
| 		if (rule->check_lvp_bits) | ||||
| 			_lv_props_match(cmd, lv, rule->check_lvp_bits, | ||||
| 					&lv_props_match_bits, &lv_props_unmatch_bits); | ||||
| 		 | ||||
| 		/* | ||||
| 		 * Evaluate if the check results pass based on the rule. | ||||
| 		 * The options are checked again here because the previous | ||||
| 		 * option validation (during command matching) does not cover | ||||
| 		 * cases where the option is combined with conditions of LV types | ||||
| 		 * or properties. | ||||
| 		 */ | ||||
|  | ||||
| 		/* Fail if any invalid options are set. */ | ||||
|  | ||||
| 		if (rule->check_opts && (rule->rule == RULE_INVALID) && opts_match_count) { | ||||
| 			memset(buf, 0, sizeof(buf)); | ||||
| 			opt_array_to_str(cmd, rule->check_opts, rule->check_opts_count, buf, sizeof(buf)); | ||||
| 			log_warn("An invalid option is set: %s", buf); | ||||
| 			ret = 0; | ||||
| 		} | ||||
|  | ||||
| 		/* Fail if any required options are not set. */ | ||||
|  | ||||
| 		if (rule->check_opts && (rule->rule == RULE_REQUIRE) && opts_unmatch_count)  { | ||||
| 			memset(buf, 0, sizeof(buf)); | ||||
| 			opt_array_to_str(cmd, rule->check_opts, rule->check_opts_count, buf, sizeof(buf)); | ||||
| 			log_warn("A required option is not set: %s", buf); | ||||
| 			ret = 0; | ||||
| 		} | ||||
|  | ||||
| 		/* Fail if the LV matches any of the invalid LV types. */ | ||||
|  | ||||
| 		if (rule->check_lvt_bits && (rule->rule == RULE_INVALID) && lv_types_match_bits) { | ||||
| 			log_warn("Command on LV %s with invalid type: %s", | ||||
| 				 display_lvname(lv), lvtype ? lvtype->name : "unknown"); | ||||
| 			ret = 0; | ||||
| 		} | ||||
|  | ||||
| 		/* Fail if the LV does not match any of the required LV types. */ | ||||
|  | ||||
| 		if (rule->check_lvt_bits && (rule->rule == RULE_REQUIRE) && !lv_types_match_bits) { | ||||
| 			memset(buf, 0, sizeof(buf)); | ||||
| 			lvt_bits_to_str(rule->check_lvt_bits, buf, sizeof(buf)); | ||||
| 			log_warn("Command on LV %s with type %s does not match required type: %s", | ||||
| 				 display_lvname(lv), lvtype ? lvtype->name : "unknown", buf); | ||||
| 			ret = 0; | ||||
| 		} | ||||
|  | ||||
| 		/* Fail if the LV matches any of the invalid LV properties. */ | ||||
|  | ||||
| 		if (rule->check_lvp_bits && (rule->rule == RULE_INVALID) && lv_props_match_bits) { | ||||
| 			memset(buf, 0, sizeof(buf)); | ||||
| 			lvp_bits_to_str(lv_props_match_bits, buf, sizeof(buf)); | ||||
| 			log_warn("Command on LV %s with invalid properties: %s", | ||||
| 				 display_lvname(lv), buf); | ||||
| 			ret = 0; | ||||
| 		} | ||||
|  | ||||
| 		/* Fail if the LV does not match any of the required LV properties. */ | ||||
|  | ||||
| 		if (rule->check_lvp_bits && (rule->rule == RULE_REQUIRE) && lv_props_unmatch_bits) { | ||||
| 			memset(buf, 0, sizeof(buf)); | ||||
| 			lvp_bits_to_str(lv_props_unmatch_bits, buf, sizeof(buf)); | ||||
| 			log_warn("Command on LV %s requires properties: %s", | ||||
| 				 display_lvname(lv), buf); | ||||
| 			ret = 0; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg, | ||||
| 			  struct dm_list *arg_lvnames, const struct dm_list *tags_in, | ||||
| 			  int stop_on_error, | ||||
| @@ -2350,6 +2882,7 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg, | ||||
| 	struct dm_str_list *sl; | ||||
| 	struct dm_list final_lvs; | ||||
| 	struct lv_list *final_lvl; | ||||
| 	struct dm_list found_arg_lvnames; | ||||
| 	struct glv_list *glvl, *tglvl; | ||||
| 	int do_report_ret_code = 1; | ||||
|  | ||||
| @@ -2360,6 +2893,7 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg, | ||||
| 		stack; | ||||
|  | ||||
| 	dm_list_init(&final_lvs); | ||||
| 	dm_list_init(&found_arg_lvnames); | ||||
|  | ||||
| 	if (!vg_check_status(vg, EXPORTED_VG)) { | ||||
| 		ret_max = ECMD_FAILED; | ||||
| @@ -2453,6 +2987,7 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg, | ||||
| 		if (lvargs_supplied && str_list_match_item(arg_lvnames, lvl->lv->name)) { | ||||
| 			/* Remove LV from list of unprocessed LV names */ | ||||
| 			str_list_del(arg_lvnames, lvl->lv->name); | ||||
| 			str_list_add(cmd->mem, &found_arg_lvnames, lvl->lv->name); | ||||
| 			process_lv = 1; | ||||
| 		} | ||||
|  | ||||
| @@ -2500,6 +3035,45 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg, | ||||
| 		if (lv_is_removed(lvl->lv)) | ||||
| 			continue; | ||||
|  | ||||
| 		/* | ||||
| 		 * The command definition may include restrictions on the | ||||
| 		 * types and properties of LVs that can be processed. | ||||
| 		 */ | ||||
|  | ||||
| 		if (!_check_lv_types(cmd, lvl->lv)) { | ||||
| 			/* FIXME: include this result in report log? */ | ||||
| 			/* FIXME: avoid duplicating message for each level */ | ||||
|  | ||||
| 			if (str_list_match_item(&found_arg_lvnames, lvl->lv->name)) { | ||||
| 				log_error("Operation not permitted (%s %d) on LV %s.", | ||||
| 					  cmd->command->command_line_id, cmd->command->command_line_enum, | ||||
| 					  display_lvname(lvl->lv)); | ||||
| 				ret_max = ECMD_FAILED; | ||||
| 			} else { | ||||
| 				log_warn("Operation not permitted (%s %d) on LV %s.", | ||||
| 					 cmd->command->command_line_id, cmd->command->command_line_enum, | ||||
| 					 display_lvname(lvl->lv)); | ||||
| 			} | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		if (!_check_lv_rules(cmd, lvl->lv)) { | ||||
| 			/* FIXME: include this result in report log? */ | ||||
| 			/* FIXME: avoid duplicating message for each level */ | ||||
|  | ||||
| 			if (str_list_match_item(&found_arg_lvnames, lvl->lv->name)) { | ||||
| 				log_error("Operation not permitted (%s %d) on LV %s.", | ||||
| 					  cmd->command->command_line_id, cmd->command->command_line_enum, | ||||
| 					  display_lvname(lvl->lv)); | ||||
| 				ret_max = ECMD_FAILED; | ||||
| 			} else { | ||||
| 				log_warn("Operation not permitted (%s %d) on LV %s.", | ||||
| 					 cmd->command->command_line_id, cmd->command->command_line_enum, | ||||
| 					 display_lvname(lvl->lv)); | ||||
| 			} | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		log_very_verbose("Processing LV %s in VG %s.", lvl->lv->name, vg->name); | ||||
|  | ||||
| 		ret = process_single_lv(cmd, lvl->lv, handle); | ||||
| @@ -3936,11 +4510,6 @@ int pvcreate_params_from_args(struct cmd_context *cmd, struct pvcreate_params *p | ||||
| 	if (pp->pva.pvmetadatacopies < 0) | ||||
| 		pp->pva.pvmetadatacopies = find_config_tree_int(cmd, metadata_pvmetadatacopies_CFG, NULL); | ||||
|  | ||||
| 	if (pp->pva.pvmetadatacopies > 2) { | ||||
| 		log_error("Metadatacopies may only be 0, 1 or 2"); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	pp->pva.ba_size = arg_uint64_value(cmd, bootloaderareasize_ARG, pp->pva.ba_size); | ||||
|  | ||||
| 	return 1; | ||||
|   | ||||
| @@ -159,6 +159,12 @@ const char *extract_vgname(struct cmd_context *cmd, const char *lv_name); | ||||
| const char *skip_dev_dir(struct cmd_context *cmd, const char *vg_name, | ||||
| 			 unsigned *dev_dir_found); | ||||
|  | ||||
| int opt_in_list_is_set(struct cmd_context *cmd, int *opts, int count, | ||||
| 		       int *match_count, int *unmatch_count); | ||||
|  | ||||
| void opt_array_to_str(struct cmd_context *cmd, int *opts, int count, | ||||
| 		      char *buf, int len); | ||||
|  | ||||
| int pvcreate_params_from_args(struct cmd_context *cmd, struct pvcreate_params *pp); | ||||
| int pvcreate_each_device(struct cmd_context *cmd, struct processing_handle *handle, struct pvcreate_params *pp); | ||||
|  | ||||
|   | ||||
| @@ -50,20 +50,41 @@ | ||||
| #define CMD_LEN 256 | ||||
| #define MAX_ARGS 64 | ||||
|  | ||||
| /* command functions */ | ||||
| typedef int (*command_fn) (struct cmd_context * cmd, int argc, char **argv); | ||||
| /* define the enums for the values accepted by command line --options, foo_VAL */ | ||||
| enum { | ||||
| #define val(a, b, c, d) a , | ||||
| #include "vals.h" | ||||
| #undef val | ||||
| }; | ||||
|  | ||||
| #define xx(a, b...) int a(struct cmd_context *cmd, int argc, char **argv); | ||||
| #include "commands.h" | ||||
| #undef xx | ||||
|  | ||||
| /* define the enums for the command line switches */ | ||||
| /* define the enums for the command line --options, foo_ARG */ | ||||
| enum { | ||||
| #define arg(a, b, c, d, e, f) a , | ||||
| #include "args.h" | ||||
| #undef arg | ||||
| }; | ||||
|  | ||||
| /* command functions */ | ||||
| #define xx(a, b...) int a(struct cmd_context *cmd, int argc, char **argv); | ||||
| #include "commands.h" | ||||
| #undef xx | ||||
|  | ||||
| /* define enums for LV properties, foo_LVP */ | ||||
| enum { | ||||
| #define lvp(a, b, c) a , | ||||
| #include "lv_props.h" | ||||
| #undef lvp | ||||
| }; | ||||
|  | ||||
| /* define enums for LV types, foo_LVT */ | ||||
| enum { | ||||
| #define lvt(a, b, c) a , | ||||
| #include "lv_types.h" | ||||
| #undef lvt | ||||
| }; | ||||
|  | ||||
| #include "command.h" | ||||
|  | ||||
| #define ARG_COUNTABLE 0x00000001	/* E.g. -vvvv */ | ||||
| #define ARG_GROUPABLE 0x00000002	/* E.g. --addtag */ | ||||
|  | ||||
| @@ -79,13 +100,13 @@ struct arg_values { | ||||
| /*	void *ptr; // Currently not used. */ | ||||
| }; | ||||
|  | ||||
| /* a global table of possible arguments */ | ||||
| /* a global table of possible --option's */ | ||||
| struct arg_props { | ||||
| 	int arg_enum; /* foo_ARG from args.h */ | ||||
| 	const char short_arg; | ||||
| 	char _padding[7]; | ||||
| 	const char *long_arg; | ||||
|  | ||||
| 	int (*fn) (struct cmd_context *cmd, struct arg_values *av); | ||||
| 	int val_enum; /* foo_VAL from vals.h */ | ||||
| 	uint32_t flags; | ||||
| 	uint32_t prio; | ||||
| }; | ||||
| @@ -96,6 +117,29 @@ struct arg_value_group_list { | ||||
| 	uint32_t prio; | ||||
| }; | ||||
|  | ||||
| /* a global table of possible --option values */ | ||||
| struct val_props { | ||||
| 	int val_enum; /* foo_VAL from vals.h */ | ||||
| 	int (*fn) (struct cmd_context *cmd, struct arg_values *av); | ||||
| 	const char *name; | ||||
| 	const char *usage; | ||||
| }; | ||||
|  | ||||
| /* a global table of possible LV properties */ | ||||
| struct lv_props { | ||||
| 	int lvp_enum; /* is_foo_LVP from lv_props.h */ | ||||
| 	const char *name; /* "lv_is_foo" used in command-lines.in */ | ||||
| 	int (*fn) (struct cmd_context *cmd, struct logical_volume *lv); /* lv_is_foo() */ | ||||
| }; | ||||
|  | ||||
| /* a global table of possible LV types */ | ||||
| /* (as exposed externally in command line interface, not exactly as internal segtype is used) */ | ||||
| struct lv_types { | ||||
| 	int lvt_enum; /* is_foo_LVT from lv_types.h */ | ||||
| 	const char *name; /* "foo" used in command-lines.in, i.e. LV_foo */ | ||||
| 	int (*fn) (struct cmd_context *cmd, struct logical_volume *lv); /* lv_is_foo() */ | ||||
| }; | ||||
|  | ||||
| #define CACHE_VGMETADATA	0x00000001 | ||||
| #define PERMITTED_READ_ONLY 	0x00000002 | ||||
| /* Process all VGs if none specified on the command line. */ | ||||
| @@ -118,19 +162,6 @@ struct arg_value_group_list { | ||||
| #define ENABLE_DUPLICATE_DEVS    0x00000400 | ||||
| /* Command does not accept tags as args. */ | ||||
| #define DISALLOW_TAG_ARGS        0x00000800 | ||||
|   | ||||
| /* a register of the lvm commands */ | ||||
| struct command { | ||||
| 	const char *name; | ||||
| 	const char *desc; | ||||
| 	const char *usage; | ||||
| 	command_fn fn; | ||||
|  | ||||
| 	unsigned flags; | ||||
|  | ||||
| 	int num_args; | ||||
| 	int *valid_args; | ||||
| }; | ||||
|  | ||||
| void usage(const char *name); | ||||
|  | ||||
| @@ -157,7 +188,15 @@ int segtype_arg(struct cmd_context *cmd, struct arg_values *av); | ||||
| int alloc_arg(struct cmd_context *cmd, struct arg_values *av); | ||||
| int locktype_arg(struct cmd_context *cmd, struct arg_values *av); | ||||
| int readahead_arg(struct cmd_context *cmd, struct arg_values *av); | ||||
| int vgmetadatacopies_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av); | ||||
| int pvmetadatacopies_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av); | ||||
| int metadatacopies_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av); | ||||
| int polloperation_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av); | ||||
| int writemostly_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av); | ||||
| int syncaction_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av); | ||||
| int reportformat_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av); | ||||
| int configreport_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av); | ||||
| int configtype_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av); | ||||
|  | ||||
| /* we use the enums to access the switches */ | ||||
| unsigned arg_count(const struct cmd_context *cmd, int a); | ||||
| @@ -199,4 +238,7 @@ int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg, | ||||
|  | ||||
| int vgchange_background_polling(struct cmd_context *cmd, struct volume_group *vg); | ||||
|  | ||||
| struct lv_props *get_lv_prop(int lvp_enum); | ||||
| struct lv_types *get_lv_type(int lvt_enum); | ||||
|  | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										136
									
								
								tools/vals.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								tools/vals.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,136 @@ | ||||
|  | ||||
| /* | ||||
|  * Define value types which describe values accepted | ||||
|  * by the --option's in args.h, and can also describe | ||||
|  * the values accepted as positional args. | ||||
|  * | ||||
|  * Previously, accepted values were only "described" | ||||
|  * by identifying the parsing function to use. | ||||
|  * | ||||
|  * Some standard val types are used by many options, | ||||
|  * e.g. many options (aa_ARG, bb_ARG, cc_ARG) all | ||||
|  * accept a number_VAL. | ||||
|  * | ||||
|  * Other special val types are used by only one option, | ||||
|  * e.g. only mirrorlog_ARG accepts a mirrorlog_VAL. | ||||
|  * This typically means that there are some specific | ||||
|  * words that are recognized after the option. | ||||
|  * | ||||
|  * Some options currently take a standard val type, | ||||
|  * (esp string_VAL), but they could be given their | ||||
|  * own custom val type.  The advantage of using a | ||||
|  * custom val type is the possibility of validating | ||||
|  * the value when parsing it with a custom parsing | ||||
|  * function, and the possibility of displaying the | ||||
|  * actual accepted values in the command usage. | ||||
|  * Without a custom val type, the code must do ad hoc | ||||
|  * validation of the string values, and the usage | ||||
|  * output for the option will only say "String" | ||||
|  * rather than giving the accepted string values. | ||||
|  * Even without a custom parsing function, there is | ||||
|  * reason to define a custom x_VAL enum so that a | ||||
|  * more descriptive usage string can be specified | ||||
|  * as opposed to just "String". | ||||
|  * | ||||
|  * Most of the val types defined here are used after | ||||
|  * --option's, and are referenced in foo_ARG entries | ||||
|  * in args.h.  But, some val types are only used to | ||||
|  * represent positional values in command definitions, | ||||
|  * e.g. vg_VAL. | ||||
|  * | ||||
|  * val(a, b, c, d) | ||||
|  * | ||||
|  * a:  foo_VAL enums | ||||
|  * b:  the function to parse and set the value | ||||
|  * c:  the name used to reference this value in command defs | ||||
|  * d:  what to display in usage output for this value | ||||
|  * | ||||
|  * command defintions will use --option NAME, where NAME | ||||
|  * is shown in val() field c.  NAME will be translated to | ||||
|  * foo_VAL enum in field a, which is used in commands[] | ||||
|  * structs. | ||||
|  * | ||||
|  * option definitions (arg.h) will reference foo_VAL enum | ||||
|  * in field a. | ||||
|  * | ||||
|  * FIXME: for specialized val types, the set of recognized | ||||
|  * words is not defined or stored in a consistent way, | ||||
|  * but is just whatever the parsing function happens to look | ||||
|  * for, so adding a new accepted value for the val type is | ||||
|  * generally making the parsing function recognize a new | ||||
|  * word, and making the implementation code also recognize | ||||
|  * that word to do something different.  This new word should | ||||
|  * then also be added to the usage string for the val type here. | ||||
|  * It would be nice if the accepted values could be defined in a | ||||
|  * more consistent way, and perhaps in a single place, perhaps in | ||||
|  * struct val_props. | ||||
|  * | ||||
|  * The usage text for an option is not always the full | ||||
|  * set of words accepted for an option, but may be a | ||||
|  * subset.  i.e. an outdated word that no longer does | ||||
|  * anything may not be shown, but may still be recognized | ||||
|  * and ignored, or an option that shouldn't be used in | ||||
|  * general isn't shown to avoid suggesting it. | ||||
|  * e.g. for --activate we show the most common "y|n|ay" | ||||
|  * without showing the lvmlockd variations "ey|sy" which | ||||
|  * are not applicable in general. | ||||
|  * | ||||
|  * FIXME: are there some specialized or irrelevant | ||||
|  * options included in the usage text below that should | ||||
|  * be removed?  Should "lvm1" be removed? | ||||
|  * | ||||
|  * For Number args that take optional units, a full usage | ||||
|  * 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 | ||||
|  * 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 | ||||
|  * 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 | ||||
|  * the same, all as 1024 SI base.  For this reason, we | ||||
|  * should avoid suggesting the upper case letters. | ||||
|  */ | ||||
|  | ||||
| val(none_VAL, NULL, "None", "ERR")             /* unused, for enum value 0 */ | ||||
| val(conststr_VAL, NULL, "ConstString", "ERR")  /* used only for command defs */ | ||||
| val(constnum_VAL, NULL, "ConstNumber", "ERR")  /* used only for command defs */ | ||||
| val(bool_VAL, yes_no_arg, "Bool", "y|n") | ||||
| val(number_VAL, int_arg, "Number", NULL) | ||||
| val(string_VAL, string_arg, "String", NULL) | ||||
| val(vg_VAL, string_arg, "VG", NULL) | ||||
| val(lv_VAL, string_arg, "LV", NULL) | ||||
| val(pv_VAL, string_arg, "PV", NULL) | ||||
| val(tag_VAL, tag_arg, "Tag", NULL) | ||||
| val(select_VAL, NULL, "Select", NULL)       /* used only for command defs */ | ||||
| val(activationmode_VAL, string_arg, "ActivationMode", "partial|degraded|complete") | ||||
| 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(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(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") | ||||
| val(vgmetadatacopies_VAL, vgmetadatacopies_arg, "MetadataCopiesVG", "all|unmanaged|Number") | ||||
| val(pvmetadatacopies_VAL, pvmetadatacopies_arg, "MetadataCopiesPV", "0|1|2") | ||||
| val(metadatacopies_VAL, metadatacopies_arg, "unused", "unused") | ||||
| val(polloperation_VAL, polloperation_arg, "PollOp", "pvmove|convert|merge|merge_thin") | ||||
| val(writemostly_VAL, writemostly_arg, "WriteMostlyPV", "PV[:t|n|y]") | ||||
| val(syncaction_VAL, syncaction_arg, "SyncAction", "check|repair") | ||||
| val(reportformat_VAL, reportformat_arg, "ReportFmt", "basic|json") | ||||
| val(configreport_VAL, configreport_arg, "ConfigReport", "log|vg|lv|pv|pvseg|seg") | ||||
| val(configtype_VAL, configtype_arg, "ConfigType", "current|default|diff|full|list|missing|new|profilable|profilable-command|profilable-metadata") | ||||
|  | ||||
| /* this should always be last */ | ||||
| val(VAL_COUNT, NULL, NULL, NULL) | ||||
|  | ||||
| @@ -482,6 +482,9 @@ static int _vgchange_metadata_copies(struct cmd_context *cmd, | ||||
| { | ||||
| 	uint32_t mda_copies = arg_uint_value(cmd, vgmetadatacopies_ARG, DEFAULT_VGMETADATACOPIES); | ||||
|  | ||||
| 	log_warn("vgchange_metadata_copies new %u vg_mda_copies %u D %u", | ||||
| 		 mda_copies, vg_mda_copies(vg), DEFAULT_VGMETADATACOPIES); | ||||
|  | ||||
| 	if (mda_copies == vg_mda_copies(vg)) { | ||||
| 		if (vg_mda_copies(vg) == VGMETADATACOPIES_UNMANAGED) | ||||
| 			log_warn("Number of metadata copies for VG %s is already unmanaged.", | ||||
|   | ||||
| @@ -157,24 +157,12 @@ int vgconvert(struct cmd_context *cmd, int argc, char **argv) | ||||
| 		return EINVALID_CMD_LINE; | ||||
| 	} | ||||
|  | ||||
| 	if (arg_is_set(cmd, metadatacopies_ARG)) { | ||||
| 		log_error("Invalid option --metadatacopies, " | ||||
| 			  "use --pvmetadatacopies instead."); | ||||
| 		return EINVALID_CMD_LINE; | ||||
| 	} | ||||
| 	if (!(cmd->fmt->features & FMT_MDAS) && | ||||
| 	    (arg_is_set(cmd, pvmetadatacopies_ARG) || | ||||
| 	     arg_is_set(cmd, metadatasize_ARG))) { | ||||
| 	    arg_is_set(cmd, pvmetadatacopies_ARG)) { | ||||
| 		log_error("Metadata parameters only apply to text format"); | ||||
| 		return EINVALID_CMD_LINE; | ||||
| 	} | ||||
|  | ||||
| 	if (arg_is_set(cmd, pvmetadatacopies_ARG) && | ||||
| 	    arg_int_value(cmd, pvmetadatacopies_ARG, -1) > 2) { | ||||
| 		log_error("Metadatacopies may only be 0, 1 or 2"); | ||||
| 		return EINVALID_CMD_LINE; | ||||
| 	} | ||||
|  | ||||
| 	if (!(cmd->fmt->features & FMT_BAS) && | ||||
| 		arg_is_set(cmd, bootloaderareasize_ARG)) { | ||||
| 		log_error("Bootloader area parameters only apply to text format"); | ||||
|   | ||||
| @@ -136,12 +136,6 @@ int vgextend(struct cmd_context *cmd, int argc, char **argv) | ||||
| 		return EINVALID_CMD_LINE; | ||||
| 	} | ||||
|  | ||||
| 	if (arg_is_set(cmd, metadatacopies_ARG)) { | ||||
| 		log_error("Invalid option --metadatacopies, " | ||||
| 			  "use --pvmetadatacopies instead."); | ||||
| 		return EINVALID_CMD_LINE; | ||||
| 	} | ||||
|  | ||||
| 	vg_name = skip_dev_dir(cmd, argv[0], NULL); | ||||
| 	argc--; | ||||
| 	argv++; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user