mirror of
git://sourceware.org/git/lvm2.git
synced 2025-09-27 05:44:18 +03:00
Compare commits
1 Commits
dev-dct-cm
...
dev-mcsont
Author | SHA1 | Date | |
---|---|---|---|
|
b51b031157 |
@@ -95,7 +95,7 @@ endif
|
||||
DISTCLEAN_TARGETS += cscope.out
|
||||
CLEAN_DIRS += autom4te.cache
|
||||
|
||||
check check_system check_cluster check_local check_lvmetad check_lvmpolld check_lvmlockd_test check_lvmlockd_dlm check_lvmlockd_sanlock unit: all
|
||||
check check_system check_cluster check_local check_lvmetad check_lvmpolld unit: all
|
||||
$(MAKE) -C test $(@)
|
||||
|
||||
conf.generate: tools
|
||||
@@ -166,11 +166,8 @@ install_tmpfiles_configuration:
|
||||
|
||||
LCOV_TRACES = libdm.info lib.info liblvm.info tools.info \
|
||||
libdaemon/client.info libdaemon/server.info \
|
||||
daemons/clvmd.info \
|
||||
daemons/dmeventd.info \
|
||||
daemons/lvmetad.info \
|
||||
daemons/lvmlockd.info \
|
||||
daemons/lvmpolld.info
|
||||
daemons/clvmd.info daemons/dmeventd.info \
|
||||
daemons/lvmetad.info
|
||||
|
||||
CLEAN_TARGETS += $(LCOV_TRACES)
|
||||
|
||||
|
@@ -1 +1 @@
|
||||
1.02.136-git (2016-09-26)
|
||||
1.02.117-git (2016-02-15)
|
||||
|
319
WHATS_NEW
319
WHATS_NEW
@@ -1,322 +1,5 @@
|
||||
Version 2.02.167 -
|
||||
======================================
|
||||
Fix a few unconverted return code values for some lvconvert error path.
|
||||
Disable lvconvert of thin pool to raid while active.
|
||||
Disable systemd service start rate limiting for lvm2-pvscan@.service.
|
||||
|
||||
Version 2.02.166 - 26th September 2016
|
||||
======================================
|
||||
Fix lvm2-activation-generator to read all LVM2 config sources. (2.02.155)
|
||||
Fix lvchange-rebuild-raid.sh to cope with older target versions.
|
||||
Use dm_config_parse_without_dup_node_check() to speedup metadata reading.
|
||||
Fix lvconvert --repair regression
|
||||
Fix reported origin lv field for cache volumes. (2.02.133)
|
||||
Always specify snapshot cow LV for monitoring not internal LV. (2.02.165)
|
||||
Fix lvchange --discard|--zero for active thin-pool.
|
||||
Enforce 4MiB or 25% metadata free space for thin pool operations.
|
||||
Fix lock-holder device for thin pool with inactive thin volumes.
|
||||
Use --alloc normal for mirror logs even if the mimages were stricter.
|
||||
Use O_DIRECT to gather metadata in lvmdump.
|
||||
Ignore creation_time when checking for matching metadata for lvmetad.
|
||||
Fix possible NULL pointer derefence when checking for monitoring.
|
||||
Add lvmreport(7) man page.
|
||||
Don't install lvmraid(7) man page when raid excluded. (2.02.165)
|
||||
Report 0% as dirty (copy%) for cache without any used block.
|
||||
Fix lvm2api reporting of cache data and metadata percent.
|
||||
Restore reporting of metadata usage for cache volumes (2.02.155).
|
||||
Support raid scrubbing on cache origin LV.
|
||||
|
||||
Version 2.02.165 - 7th September 2016
|
||||
Version 2.02.143 -
|
||||
=====================================
|
||||
Add lvmraid(7) man page.
|
||||
Use udev db to check for mpath components before running pvscan for lvmetad.
|
||||
Use lsblk -s and lsblk -O in lvmdump only if these options are supported.
|
||||
Fix number of stripes shown in lvcreate raid10 message when too many.
|
||||
Change lvmdbusd to use new lvm shell facilities.
|
||||
Do not monitor cache-pool metadata when LV is just being cleared.
|
||||
Add allocation/cache_pool_max_chunks to prevent misuse of cache target.
|
||||
Give error not segfault in lvconvert --splitmirrors when PV lies outside LV.
|
||||
Fix typo in report/columns_as_rows config option name recognition (2.02.99).
|
||||
Avoid PV tags when checking allocation against parallel PVs.
|
||||
Disallow mirror conversions of raid10 volumes.
|
||||
Fix dmeventd unmonitoring when segment type (and dso) changes.
|
||||
Don't allow lvconvert --repair on raid0 devices or attempt to monitor them.
|
||||
No longer adjust incorrect number of raid stripes supplied to lvcreate.
|
||||
Move lcm and gcd to lib/misc.
|
||||
Fix vgsplit of external origins. (2.02.162)
|
||||
Prohibit creation of RAID LVs unless VG extent size is at least the page size.
|
||||
Suppress some unnecessary --stripesize parameter warnings.
|
||||
Fix 'pvmove -n name ...' to prohibit collocation of RAID SubLVs
|
||||
|
||||
Version 2.02.164 - 15th August 2016
|
||||
===================================
|
||||
Fix selection of PVs when allocating raid0_meta.
|
||||
Fix sdbus socket leak leading to hang in lvmnotify.
|
||||
Specify max stripes for raid LV types: raid0:64; 1:10; 4,5:63; 6:62; 10:32.
|
||||
Avoid double suffix when naming _rmeta LV paired with _rimage LV.
|
||||
|
||||
Version 2.02.163 - 10th August 2016
|
||||
===================================
|
||||
Add profile for lvmdbusd which uses lvm shell json report output.
|
||||
Restrict in-command modification of some parms in lvm shell.
|
||||
Apply LVM_COMMAND_PROFILE early for lvm shell.
|
||||
Refactor reporting so lvm shell log report collects whole of cmd execution.
|
||||
Support LVM_*_FD envvars to redirect output to file descriptors.
|
||||
Limit use of --corelog and --mirrorlog to mirrors in lvconvert.
|
||||
Reject --nosync option for RAID6 LVs in lvcreate.
|
||||
Do not refresh whole cmd context if profile dropped after processing LVM cmd.
|
||||
Support straightforward lvconvert between striped and raid4 LVs.
|
||||
Support straightforward lvconvert between raid1 and mirror LVs.
|
||||
Report supported conversions when asked for unsupported raid lvconvert.
|
||||
Add "--rebuild PV" option to lvchange to allow for PV selective rebuilds.
|
||||
Preserve existing mirror region size when using --repair.
|
||||
Forbid stripe parameters with lvconvert --repair.
|
||||
Unify stripe size validation into get_stripe_params to catch missing cases.
|
||||
Further lvconvert validation logic refactoring.
|
||||
|
||||
Version 2.02.162 - 28th July 2016
|
||||
=================================
|
||||
Extend vg_validate also to check raid configurations thoroughly.
|
||||
Support lvconvert -Zn also when doing full cache pool conversion.
|
||||
Suppress not zeroing warn when converting to thin LV for non-zeroing tpool.
|
||||
Fix automatic updates of PV extension headers to newest version.
|
||||
Improve lvconvert --trackchanges validation to require --splitmirrors 1.
|
||||
Add note about lastlog built-in command to lvm man page.
|
||||
Fix unrecognised segtype flag message.
|
||||
lvconvert not clears cache pool metadata ONLY with -Zn.
|
||||
Add allocation/raid_stripe_all_devices to reinstate previous behaviour.
|
||||
Create raid stripes across fixed small numbers of PVs instead of all PVs.
|
||||
Enabled lvconvert --uncache to work with partial VG.
|
||||
Disallow lvconvert --replace with raid0* LVs.
|
||||
Fix some lvmetad changed VG metadata notifications that sent uncommitted data.
|
||||
|
||||
Version 2.02.161 - 15th July 2016
|
||||
=================================
|
||||
Prohibit some lvchange/lvresize that were failing on raid0 volumes.
|
||||
Fix segfaults in complex vgsplits. (2.02.159)
|
||||
Reformat unwieldy lvconvert man page.
|
||||
Allow --force to be passed through to pvcreate from vgcreate. (2.02.144)
|
||||
Fix lvresize of filesystem when LV has already right size (2.02.141)
|
||||
New LVM_LOG_FILE_MAX_LINES env var to limit max size of created logs.
|
||||
|
||||
Version 2.02.160 - 6th July 2016
|
||||
================================
|
||||
Minor fixes from coverity.
|
||||
|
||||
Version 2.02.159 - 6th July 2016
|
||||
================================
|
||||
Add raid0_meta segment type that provides metadata space for raid conversions.
|
||||
Fix created link for a used pool for vgmknode.
|
||||
Introduce and use is_power_of_2 macro.
|
||||
Support conversions between striped and raid0 segment types.
|
||||
Add infrastructure for raid takeover lvconvert options.
|
||||
|
||||
Version 2.02.158 - 25th June 2016
|
||||
=================================
|
||||
Add a more efficient native vgimportclone command to replace the script.
|
||||
Make lvmlockd always attempt to connect to lvmetad if no connection exists.
|
||||
Let lvmetad handle new connections after shutdown signal.
|
||||
Disable lvmetad when vgcfgrestore begins and enable it again after.
|
||||
Make pvscan do activation if lvmetad is configured but not running.
|
||||
Fix rescanning the PVs for a single VG when using lvmetad.
|
||||
Pool metadata lvresize uses now same code as resize of normal volume.
|
||||
Preserve monitoring status when updating thin-pool metadata.
|
||||
Return 0 (inactive) when status cannot be queried in _lv_active().
|
||||
Switch to log_warn() for failing activation status query.
|
||||
Replace vgimportclone script with binary.
|
||||
While lvmetad is shutting down, continue handling all connections cleanly.
|
||||
Refactor lvconvert argument handling code.
|
||||
Notify lvmetad when vgcfgrestore changes VG metadata.
|
||||
Add --logonly option to report only cmd log for a command, not other reports.
|
||||
Add log/command_log_selection to configure default selection used on cmd log.
|
||||
Use 'orphan' object type in cmd log for groups to collect PVs not yet in VGs.
|
||||
Add lvm lastlog command for query and display of last cmd's log in lvm shell.
|
||||
Report per-object return codes via cmd log while processing multiple objects.
|
||||
Annotate processing code with log report hooks for per-object command log.
|
||||
Also pass common printed messages (besides warnings and errors) to log report.
|
||||
Log warnings and errors via report during cmd processing if this is enabled.
|
||||
Make it possible to iterate over internal 'orphan' VGs in process_each_vg fn.
|
||||
Make -S|--select option groupable that allows this option to be repeated.
|
||||
Make -O|--sort option groupable that allows this option to be repeated.
|
||||
Add --configreport option to select report for which next options are applied.
|
||||
Add support for priorities on grouping command arguments.
|
||||
Add report/{pvs,vgs,lvs,pvsegs,segs}_{cols,sort}_full to lvm.conf.
|
||||
Add lvm fullreport command for joined PV, VG, LV and segment report per VG.
|
||||
Integrate report group handling and cmd log report into cmd processing code.
|
||||
Add log/report_command_log to lvm.conf to enable or disable cmd log report.
|
||||
Add log/report_output_format to lvm.conf for default report output format.
|
||||
Recognize --reportformat {basic|json} option to select report output format.
|
||||
Add log/command_log_{sort,cols} to lvm.conf to configure command log report.
|
||||
Add log_object_{type,name,id,group,group_id} fields to cmd log.
|
||||
Add log_{seq_num,type,context,message,errno,ret_code} fields to cmd log.
|
||||
Add CMDLOG report type - a separate report type for command logging.
|
||||
|
||||
Version 2.02.157 - 17th June 2016
|
||||
=================================
|
||||
Change pvscan --cache -aay to scan locally if lvmetad fails.
|
||||
|
||||
Version 2.02.156 - 11th June 2016
|
||||
=================================
|
||||
Don't allow duplicate orphan PVs to be used with vgcreate/vgextend/pvcreate.
|
||||
Improve handling of lvmetad update failures.
|
||||
Yes/No prompt accepts '^[ ^t]*([Yy]([Ee]([Ss]|)|)|[Nn]([Oo]|))[ ^t]*$'.
|
||||
If available, also collect output from lsblk command when running lvmdump -s.
|
||||
|
||||
Version 2.02.155 - 3rd June 2016
|
||||
================================
|
||||
Reject PV tags on pvmove cmdline because only 1 PV is supported. (2.02.141)
|
||||
Fix compilation error when building with configure --disable-devmapper.
|
||||
Fix lvmconfig --type diff to display complete diff if config cascade used.
|
||||
Automatically filter out partitioned loop devices with partscan (losetup -P).
|
||||
Fix lvm devtypes internal error if -S used with field name from pvs/vgs/lvs.
|
||||
When reporting Data%,Snap%,Meta%,Cpy%Sync use single ioctl per LV.
|
||||
Add lvseg_percent_with_info_and_seg_status() for percent retrieval.
|
||||
Enhance internal seg_status handling to understand snapshots better.
|
||||
When refresh failed in suspend, call resume upon error path.
|
||||
Support passthrough cache mode when waiting for clean cache.
|
||||
Check cache status only for 'in-use' cache pools.
|
||||
Extend setup_task() to preset flushing for dm_task object.
|
||||
When checking LV is a merging COW, validate its a COW LV first.
|
||||
Correcting value in copy_percent() for 100%.
|
||||
Update vgreduce to use process_each_vg.
|
||||
Update lvconvert to use process_each_lv.
|
||||
Update pvscan to use process_each_vg for autoactivation.
|
||||
Add basic support for --type raid0 using md.
|
||||
Add support for lvchange --cachemode for cached LV.
|
||||
Fix liblvm2app error handling when setting up context.
|
||||
Delay liblvm2app init in python code until it is needed.
|
||||
Simplify thread locking in lvmetad to fix locking problems.
|
||||
Allow pvremove -ff to remove a duplicate PV.
|
||||
Fix lvm2-activation-generator to read lvm.conf without full command setup.
|
||||
Allow a minimal context to be used in lvm2app for reading lvm.conf.
|
||||
|
||||
Version 2.02.154 - 14th May 2016
|
||||
================================
|
||||
Fix liblvm segfault after failure initialising lvmetad connection.
|
||||
Retry open without O_NOATIME if it fails (not file owner/CAP_FOWNER).
|
||||
Split _report into one fn for options and arguments and one for processing.
|
||||
|
||||
Version 2.02.153 - 7th May 2016
|
||||
===============================
|
||||
Change warning messages related to duplicate PVs.
|
||||
A named device is always processed itself, not switched for a duplicate.
|
||||
Add PV attr "d" and report field "duplicate" for duplicate PVs.
|
||||
Add config setting to disallow VG changes when duplicate PVs exist.
|
||||
Use device size and active LVs to choose the preferred duplicate PV.
|
||||
Disable lvmetad when duplicate PVs are seen.
|
||||
Support --chunksize option also when caching LV when possible.
|
||||
Add function to check for target presence and version via 1 ioctl.
|
||||
|
||||
Version 2.02.152 - 30th April 2016
|
||||
==================================
|
||||
Use any inherited tags when wiping metadata sub LVs to ensure activation.
|
||||
Add str_list_wipe.
|
||||
Improve support for interrupting procesing of volumes during lvchange.
|
||||
Use failed command return code when lvchanging read-only volume.
|
||||
Show creation transaction_id and zeroing state of pool with thin volume.
|
||||
Stop checking for dm_cache_mq policy with cache target 1.9 (alias to smq).
|
||||
Check first /sys/module/dm_* dir existance before using modprobe.
|
||||
Remove mpath from 10-dm.rules, superseded by 11-dm-mpath.rules (mpath>=0.6.0).
|
||||
|
||||
Version 2.02.151 - 23rd April 2016
|
||||
==================================
|
||||
Fix error path after reusing of _setup_task (2.02.150).
|
||||
Fix memory access for empty sysfs values (2.02.149).
|
||||
Disable lvmetad when lvm1 metadata is seen, so commands revert to scanning.
|
||||
Suppress errors when snapshot merge gets delayed because volume is in use.
|
||||
Avoid internal snapshot LV names in messages.
|
||||
Autodetect and use /run/lock dir when available instead of /var/lock.
|
||||
lvchange --refresh for merging thin origin will retry to deactivate snapshot.
|
||||
Recognize in-progress snapshot merge for thin volumes from dm table.
|
||||
Avoid deciding to initiate a pending snapshot merge during resume.
|
||||
Improve retrying lvmetad requests while lvmetad is being updated.
|
||||
Read devices instead of using the lvmetad cache if rescan fails.
|
||||
Move lvmetad token/filter check and device rescan to the start of commands.
|
||||
Don't try deactivating fictional internal LV before snapshot merge. (2.02.105)
|
||||
When not obtaining devs from udev, check they exist before caching them.
|
||||
Detect device mismatch also when compiling without udev support.
|
||||
|
||||
Version 2.02.150 - 9th April 2016
|
||||
=================================
|
||||
Avoid using flushing dm status ioctl when checking for usable DM device.
|
||||
Check for devices without LVM- uuid prefix only with kernels < 3.X.
|
||||
Reuse %FREE size aproximation with lvcreate -l%PVS thin-pool.
|
||||
Allow the lvmdump directory to exist already provided it is empty.
|
||||
Show lvconverted percentage with 2 decimal digits.
|
||||
Fix regression in suspend when repairing --type mirror (2.02.133).
|
||||
|
||||
Version 2.02.149 - 1st April 2016
|
||||
=================================
|
||||
Do not flush thin-pool when checking metadata fullness.
|
||||
Remove spurious error about no value in /sys/dev/block/major:minor/dm/uuid.
|
||||
Fix device mismatch detection for LV if persistent .cache file is used.
|
||||
Fix holder device not being found in /dev while sysfs has it during dev scan.
|
||||
|
||||
Version 2.02.148 - 26th March 2016
|
||||
==================================
|
||||
Introduce TARGET_NAME and MODULE NAME macros.
|
||||
Replace hard-coded module and target names with macros.
|
||||
Add pv_major and pv_minor report fields.
|
||||
Detect and warn about mismatch between devices used and assumed for an LV.
|
||||
|
||||
Version 2.02.147 - 19th March 2016
|
||||
==================================
|
||||
If available, use /proc/self/mountinfo to detect mounted volume in fsadm.
|
||||
Fix resize of stacked raid thin data volume (2.02.141).
|
||||
Fix test for lvremove failure in lvconvert --uncache (2.02.146).
|
||||
|
||||
Version 2.02.146 - 11th March 2016
|
||||
==================================
|
||||
More man page cleanups in lvconvert.
|
||||
Fix makefile vpath in /udev when generating udev rules files.
|
||||
Another attempt to improve VG name parsing for lvconvert (2.02.144).
|
||||
Use new cache status info and skip flushing for failed cache.
|
||||
Support --uncache with missing PVs.
|
||||
Tidy report field names, headings and widths.
|
||||
Add vgscan --notifydbus to send a dbus notification.
|
||||
Add dbus notification from commands after a PV/VG/LV changes state.
|
||||
|
||||
Version 2.02.145 - 4th March 2016
|
||||
=================================
|
||||
Make it possible to use lvremove and lvrename on historical LVs.
|
||||
For historical LVs, report 'none' for lv_layout and 'history' for lv_role.
|
||||
Add full_{ancestors,descendants} fields to report LV ancestry with history.
|
||||
Report (h)istorical state within 5th bit (State) of the lv_attr field.
|
||||
Add lv_historical reporting field to report if LV is historical or not.
|
||||
Add lv_time_removed reporting field to display removal time for hist. LVs.
|
||||
Report lv_name, lv_uuid, vg_name, lv_time for historical LVs.
|
||||
Add --nohistory switch to lvremove to disable history recording on demand.
|
||||
Add -H|--history switch to lvs and lvdisplay to include historical LVs.
|
||||
Create historical LVs out of removed thin snapshot LVs and record in history.
|
||||
Add metadata/lvs_history_retention_time for automatic removal of hist. LVs.
|
||||
Add metadata/record_lvs_history config for switching LV history recording.
|
||||
Add support and infrastructure for tracking historical LVs.
|
||||
Improve lvconvert man page.
|
||||
Add kernel_cache_policy lvs field.
|
||||
Display [unknown] instead of 'unknown device' in pvs output.
|
||||
Fix error path when pvcreate allocation fails (2.02.144).
|
||||
Display [unknown] instead of blank for unknown VG names in pvs output.
|
||||
|
||||
Version 2.02.144 - 26th February 2016
|
||||
=====================================
|
||||
Use new PV processing code in pvcreate/vgcreate/vgextend/pvremove.
|
||||
Add new PV processing code that prompts user without locks held.
|
||||
Prevent lvmlockd blocking with new flag requiring sanlock 3.3.0.
|
||||
Only show (u)sed pv_attr char when PV is not (a)llocatable. (2.02.143)
|
||||
Update makefile to generate lcov output also for lvmpolld and lvmlockd.
|
||||
Fix SystemdService lvm2-lvmdbusd.service name.
|
||||
Improve support for env LVM_VG_NAME for reference VG name in lvconvert.
|
||||
Fix regression when lvresize accepted zero sizes. (2.02.141)
|
||||
Always warn user about PV in use even when pvremove uses --force --force.
|
||||
Use uninitialized pool header detection in all cases.
|
||||
Fix read error detection when checking for uninitialized thin-pool header.
|
||||
Fix error path for internal error in lvmetad VG lookup code.
|
||||
|
||||
Version 2.02.143 - 21st February 2016
|
||||
=====================================
|
||||
Fix error path when sending thin-pool message fails in update_pool_lv().
|
||||
Support reporting CheckNeeded and Fail state for thin-pool and thin LV.
|
||||
For failing thin-pool and thin volume correctly report percentage as INVALID.
|
||||
Report -1, not 'unkown' for lv_{snapshot_invalid,merge_failed} with --binary.
|
||||
Add configure --enable-dbus-service for an LVM D-Bus service.
|
||||
Replace configure --enable-python_bindings with python2 and python3 versions.
|
||||
|
122
WHATS_NEW_DM
122
WHATS_NEW_DM
@@ -1,123 +1,5 @@
|
||||
Version 1.02.136 -
|
||||
======================================
|
||||
Check and report pthread_sigmask() failure in dmeventd.
|
||||
Check mem alloc fail in _canonicalize_field_ids().
|
||||
Use unsigned math when checking more then 31 legs of raid.
|
||||
Fix 'dmstats delete' with dmsetup older than v1.02.129
|
||||
Fix stats walk segfault with dmsetup older than v1.02.129
|
||||
|
||||
Version 1.02.135 - 26th September 2016
|
||||
======================================
|
||||
Fix man entry for dmsetup status.
|
||||
Introduce new dm_config_parse_without_dup_node_check().
|
||||
Don't omit last entry in dmstats list --group.
|
||||
|
||||
Version 1.02.134 - 7th September 2016
|
||||
Version 1.02.117 -
|
||||
=====================================
|
||||
Improve explanation of udev fallback in libdevmapper.h.
|
||||
|
||||
Version 1.02.133 - 10th August 2016
|
||||
===================================
|
||||
Add dm_report_destroy_rows/dm_report_group_output_and_pop_all for lvm shell.
|
||||
Adjust group handling and json production for lvm shell.
|
||||
|
||||
Version 1.02.132 - 28th July 2016
|
||||
=================================
|
||||
Fix json reporting to escape '"' character that may appear in reported string.
|
||||
|
||||
Version 1.02.131 - 15th July 2016
|
||||
=================================
|
||||
Disable queueing on mpath devs in blk-availability systemd service/initscript.
|
||||
Add new -m|--mpathoption disablequeueing to blkdeactivate.
|
||||
Automatically group regions with 'create --segments' unless --nogroup.
|
||||
Fix resource leak when deleting the first member of a group.
|
||||
Allow --bounds with 'create --filemap' for dmstats.
|
||||
Enable creation of filemap regions with histograms.
|
||||
Enable histogram aggregation for regions with more than one area.
|
||||
Enable histogram aggregation for groups of regions.
|
||||
Add a --filemap option to 'dmstats create' to allow mapping of files.
|
||||
Add dm_stats_create_regions_from_fd() to map file extents to regions.
|
||||
|
||||
Version 1.02.130 - 6th July 2016
|
||||
================================
|
||||
Minor fixes from coverity.
|
||||
|
||||
Version 1.02.129 - 6th July 2016
|
||||
================================
|
||||
Update default dmstats field selections for groups.
|
||||
Add 'obj_type', 'group_id', and 'statsname' fields to dmstats reports.
|
||||
Add --area, --region, and --group to dmstats to control object selection.
|
||||
Add --alias, --groupid, --regions to dmstats for group creation and deletion.
|
||||
Add 'group' and 'ungroup' commands to dmstats.
|
||||
Allow dm_stats_delete_group() to optionally delete all group members.
|
||||
Add dm_stats_get_object_type() to return the type of object present.
|
||||
Add dm_stats_walk_init() allowing control of objects visited by walks.
|
||||
Add dm_stats_get_group_descriptor() to return the member list as a string.
|
||||
Introduce dm_stats_get_nr_groups() and dm_stats_group_present().
|
||||
Add dm_stats_{get,set}_alias() to set and retrieve alias names for groups.
|
||||
Add dm_stats_get_group_id() to return the group ID for a given region.
|
||||
Add dm_stats_{create,delete}_group() to allow grouping of stats regions.
|
||||
Add enum-driven dm_stats_get_{metric,counter}() interfaces.
|
||||
Add dm_bitset_parse_list() to parse a string representation of a bitset.
|
||||
Thin dmeventd plugin umounts lvm2 volume only when pool is 95% or more.
|
||||
|
||||
Version 1.02.128 - 25th June 2016
|
||||
=================================
|
||||
Recognize 'all' keyword used in selection as synonym for "" (no selection).
|
||||
Add dm_report_set_selection to set selection for multiple output of report.
|
||||
Add DM_REPORT_OUTPUT_MULTIPLE_TIMES flag for multiple output of same report.
|
||||
Move field width handling/sort init from dm_report_object to dm_report_output.
|
||||
Add _LOG_BYPASS_REPORT flag for bypassing any log report currently set.
|
||||
Introduce DM_REPORT_GROUP_JSON for report group with JSON output format.
|
||||
Introduce DM_REPORT_GROUP_BASIC for report group with basic report output.
|
||||
Introduce DM_REPORT_GROUP_SINGLE for report group having single report only.
|
||||
Add dm_report_group_{create,push,pop,destroy} to support report grouping.
|
||||
|
||||
Version 1.02.127 - 11th June 2016
|
||||
=================================
|
||||
Fix blkdeactivate regression causing skipping of dm + md devices. (1.02.126)
|
||||
|
||||
Version 1.02.126 - 3rd June 2016
|
||||
================================
|
||||
Report passthrough caching mode when parsing cache mode.
|
||||
|
||||
Version 1.02.125 - 14th May 2016
|
||||
================================
|
||||
Show library version in message even if dm driver version is unavailable.
|
||||
|
||||
Version 1.02.124 - 30th April 2016
|
||||
==================================
|
||||
Add dm_udev_wait_immediate to libdevmapper for waiting outside the library.
|
||||
|
||||
Version 1.02.123 - 23rd April 2016
|
||||
==================================
|
||||
Do not strip LVM- when debug reporting not found uuid.
|
||||
|
||||
Version 1.02.122 - 9th April 2016
|
||||
=================================
|
||||
Change log_debug ioctl flags from single characters into words.
|
||||
|
||||
Version 1.02.121 - 26th March 2016
|
||||
==================================
|
||||
Adjust raid status function.
|
||||
|
||||
Version 1.02.120 - 11th March 2016
|
||||
==================================
|
||||
Improve parsing of cache status and report Fail, Error, needs_check, ro.
|
||||
|
||||
Version 1.02.119 - 4th March 2016
|
||||
=================================
|
||||
Fix dm_config_write_node and variants to return error on subsection failures.
|
||||
Remove 4096 char limit due to buffer size if writing dm_config_node.
|
||||
|
||||
Version 1.02.118 - 26th February 2016
|
||||
=====================================
|
||||
Fix string boundary check in _get_canonical_field_name().
|
||||
Always initialized hist struct in _stats_parse_histogram().
|
||||
|
||||
Version 1.02.117 - 21st February 2016
|
||||
=====================================
|
||||
Improve status parsing for thin-pool and thin devices.
|
||||
|
||||
Version 1.02.116 - 15th February 2016
|
||||
=====================================
|
||||
@@ -180,7 +62,7 @@ Version 1.02.110 - 30th October 2015
|
||||
Correct use of max_write_behind parameter when generating raid target line.
|
||||
Fix dm-event systemd service to make sure it is executed before mounting.
|
||||
|
||||
Version 1.02.109 - 22nd September 2015
|
||||
Version 1.02.109 - 22nd September 2016
|
||||
======================================
|
||||
Update man pages for dmsetup and dmstats.
|
||||
Improve help text for dmsetup.
|
||||
|
@@ -24,8 +24,7 @@ PROFILES=$(PROFILE_TEMPLATES) \
|
||||
$(srcdir)/cache-mq.profile \
|
||||
$(srcdir)/cache-smq.profile \
|
||||
$(srcdir)/thin-generic.profile \
|
||||
$(srcdir)/thin-performance.profile \
|
||||
$(srcdir)/lvmdbusd.profile
|
||||
$(srcdir)/thin-performance.profile
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
|
@@ -16,20 +16,15 @@ allocation {
|
||||
cache_settings {
|
||||
}
|
||||
}
|
||||
log {
|
||||
report_command_log=0
|
||||
command_log_sort="log_seq_num"
|
||||
command_log_cols="log_seq_num,log_type,log_context,log_object_type,log_object_name,log_object_id,log_object_group,log_object_group_id,log_message,log_errno,log_ret_code"
|
||||
command_log_selection="!(log_type=status && message=success)"
|
||||
}
|
||||
|
||||
global {
|
||||
units="h"
|
||||
si_unit_consistency=1
|
||||
suffix=1
|
||||
lvdisplay_shows_full_device_path=0
|
||||
}
|
||||
|
||||
report {
|
||||
output_format="basic"
|
||||
compact_output=0
|
||||
compact_output_cols=""
|
||||
aligned=1
|
||||
@@ -39,7 +34,7 @@ report {
|
||||
list_item_separator=","
|
||||
prefixes=0
|
||||
quoted=1
|
||||
columns_as_rows=0
|
||||
colums_as_rows=0
|
||||
binary_values_as_numeric=0
|
||||
time_format="%Y-%m-%d %T %z"
|
||||
devtypes_sort="devtype_name"
|
||||
@@ -60,15 +55,5 @@ report {
|
||||
pvsegs_sort="pv_name,pvseg_start"
|
||||
pvsegs_cols="pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size"
|
||||
pvsegs_cols_verbose="pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size,lv_name,seg_start_pe,segtype,seg_pe_ranges"
|
||||
vgs_cols_full="vg_all"
|
||||
pvs_cols_full="pv_all"
|
||||
lvs_cols_full="lv_all"
|
||||
pvsegs_cols_full="pvseg_all,pv_uuid,lv_uuid"
|
||||
segs_cols_full="seg_all,lv_uuid"
|
||||
vgs_sort_full="vg_name"
|
||||
pvs_sort_full="pv_name"
|
||||
lvs_sort_full="vg_name,lv_name"
|
||||
pvsegs_sort_full="pv_uuid,pvseg_start"
|
||||
segs_sort_full="lv_uuid,seg_start"
|
||||
mark_hidden_devices=1
|
||||
}
|
||||
|
@@ -299,19 +299,6 @@ devices {
|
||||
# generally do. If enabled, discards will only be issued if both the
|
||||
# storage and kernel provide support.
|
||||
issue_discards = 0
|
||||
|
||||
# Configuration option devices/allow_changes_with_duplicate_pvs.
|
||||
# Allow VG modification while a PV appears on multiple devices.
|
||||
# When a PV appears on multiple devices, LVM attempts to choose the
|
||||
# best device to use for the PV. If the devices represent the same
|
||||
# underlying storage, the choice has minimal consequence. If the
|
||||
# devices represent different underlying storage, the wrong choice
|
||||
# can result in data loss if the VG is modified. Disabling this
|
||||
# setting is the safest option because it prevents modifying a VG
|
||||
# or activating LVs in it while a PV appears on multiple devices.
|
||||
# Enabling this setting allows the VG to be used as usual even with
|
||||
# uncertain devices.
|
||||
allow_changes_with_duplicate_pvs = 0
|
||||
}
|
||||
|
||||
# Configuration section allocation.
|
||||
@@ -377,14 +364,6 @@ allocation {
|
||||
# The default setting changed in version 2.02.85.
|
||||
mirror_logs_require_separate_pvs = 0
|
||||
|
||||
# Configuration option allocation/raid_stripe_all_devices.
|
||||
# Stripe across all PVs when RAID stripes are not specified.
|
||||
# If enabled, all PVs in the VG or on the command line are used for raid0/4/5/6/10
|
||||
# when the command does not specify the number of stripes to use.
|
||||
# This was the default behaviour until release 2.02.162.
|
||||
# This configuration option has an automatic default value.
|
||||
# raid_stripe_all_devices = 0
|
||||
|
||||
# Configuration option allocation/cache_pool_metadata_require_separate_pvs.
|
||||
# Cache pool metadata and data will always use different PVs.
|
||||
cache_pool_metadata_require_separate_pvs = 0
|
||||
@@ -428,12 +407,6 @@ allocation {
|
||||
# 32KiB to 1GiB in multiples of 32.
|
||||
# This configuration option does not have a default value defined.
|
||||
|
||||
# Configuration option allocation/cache_pool_max_chunks.
|
||||
# The maximum number of chunks in a cache pool.
|
||||
# For cache target v1.9 the recommended maximumm is 1000000 chunks.
|
||||
# Using cache pool with more chunks may degrade cache performance.
|
||||
# This configuration option does not have a default value defined.
|
||||
|
||||
# Configuration option allocation/thin_pool_metadata_require_separate_pvs.
|
||||
# Thin pool metdata and data will always use different PVs.
|
||||
thin_pool_metadata_require_separate_pvs = 0
|
||||
@@ -492,55 +465,6 @@ allocation {
|
||||
# How LVM log information is reported.
|
||||
log {
|
||||
|
||||
# Configuration option log/report_command_log.
|
||||
# Enable or disable LVM log reporting.
|
||||
# If enabled, LVM will collect a log of operations, messages,
|
||||
# per-object return codes with object identification and associated
|
||||
# error numbers (errnos) during LVM command processing. Then the
|
||||
# log is either reported solely or in addition to any existing
|
||||
# reports, depending on LVM command used. If it is a reporting command
|
||||
# (e.g. pvs, vgs, lvs, lvm fullreport), then the log is reported in
|
||||
# addition to any existing reports. Otherwise, there's only log report
|
||||
# on output. For all applicable LVM commands, you can request that
|
||||
# the output has only log report by using --logonly command line
|
||||
# option. Use log/command_log_cols and log/command_log_sort settings
|
||||
# to define fields to display and sort fields for the log report.
|
||||
# You can also use log/command_log_selection to define selection
|
||||
# criteria used each time the log is reported.
|
||||
# This configuration option has an automatic default value.
|
||||
# report_command_log = 0
|
||||
|
||||
# Configuration option log/command_log_sort.
|
||||
# List of columns to sort by when reporting command log.
|
||||
# See <lvm command> --logonly --configreport log -o help
|
||||
# for the list of possible fields.
|
||||
# This configuration option has an automatic default value.
|
||||
# command_log_sort = "log_seq_num"
|
||||
|
||||
# Configuration option log/command_log_cols.
|
||||
# List of columns to report when reporting command log.
|
||||
# See <lvm command> --logonly --configreport log -o help
|
||||
# for the list of possible fields.
|
||||
# This configuration option has an automatic default value.
|
||||
# command_log_cols = "log_seq_num,log_type,log_context,log_object_type,log_object_name,log_object_id,log_object_group,log_object_group_id,log_message,log_errno,log_ret_code"
|
||||
|
||||
# Configuration option log/command_log_selection.
|
||||
# Selection criteria used when reporting command log.
|
||||
# You can define selection criteria that are applied each
|
||||
# time log is reported. This way, it is possible to control the
|
||||
# amount of log that is displayed on output and you can select
|
||||
# only parts of the log that are important for you. To define
|
||||
# selection criteria, use fields from log report. See also
|
||||
# <lvm command> --logonly --configreport log -S help for the
|
||||
# list of possible fields and selection operators. You can also
|
||||
# define selection criteria for log report on command line directly
|
||||
# using <lvm command> --configreport log -S <selection criteria>
|
||||
# which has precedence over log/command_log_selection setting.
|
||||
# For more information about selection criteria in general, see
|
||||
# lvm(8) man page.
|
||||
# This configuration option has an automatic default value.
|
||||
# command_log_selection = "!(log_type=status && message=success)"
|
||||
|
||||
# Configuration option log/verbose.
|
||||
# Controls the messages sent to stdout or stderr.
|
||||
verbose = 0
|
||||
@@ -601,7 +525,7 @@ log {
|
||||
# debug output if the class is listed here. Classes currently
|
||||
# available: memory, devices, activation, allocation, lvmetad,
|
||||
# metadata, cache, locking, lvmpolld. Use "all" to see everything.
|
||||
debug_classes = [ "memory", "devices", "activation", "allocation", "lvmetad", "metadata", "cache", "locking", "lvmpolld", "dbus" ]
|
||||
debug_classes = [ "memory", "devices", "activation", "allocation", "lvmetad", "metadata", "cache", "locking", "lvmpolld" ]
|
||||
}
|
||||
|
||||
# Configuration section backup.
|
||||
@@ -927,23 +851,13 @@ global {
|
||||
# devices/global_filter.
|
||||
use_lvmetad = @DEFAULT_USE_LVMETAD@
|
||||
|
||||
# Configuration option global/lvmetad_update_wait_time.
|
||||
# The number of seconds a command will wait for lvmetad update to finish.
|
||||
# After waiting for this period, a command will not use lvmetad, and
|
||||
# will revert to disk scanning.
|
||||
# This configuration option has an automatic default value.
|
||||
# lvmetad_update_wait_time = 10
|
||||
|
||||
# Configuration option global/use_lvmlockd.
|
||||
# Use lvmlockd for locking among hosts using LVM on shared storage.
|
||||
# Applicable only if LVM is compiled with lockd support in which
|
||||
# case there is also lvmlockd(8) man page available for more
|
||||
# information.
|
||||
# See lvmlockd(8) for more information.
|
||||
use_lvmlockd = 0
|
||||
|
||||
# Configuration option global/lvmlockd_lock_retries.
|
||||
# Retry lvmlockd lock requests this many times.
|
||||
# Applicable only if LVM is compiled with lockd support
|
||||
# This configuration option has an automatic default value.
|
||||
# lvmlockd_lock_retries = 3
|
||||
|
||||
@@ -953,8 +867,7 @@ global {
|
||||
# LVs have been created, the internal LV needs to be extended. lvcreate
|
||||
# will automatically extend the internal LV when needed by the amount
|
||||
# specified here. Setting this to 0 disables the automatic extension
|
||||
# and can cause lvcreate to fail. Applicable only if LVM is compiled
|
||||
# with lockd support
|
||||
# and can cause lvcreate to fail.
|
||||
# This configuration option has an automatic default value.
|
||||
# sanlock_lv_extend = 256
|
||||
|
||||
@@ -1101,14 +1014,7 @@ global {
|
||||
# a native systemd service, which allows it to be started on demand,
|
||||
# and to use its own control group. When this option is disabled, LVM
|
||||
# commands will supervise long running operations by forking themselves.
|
||||
# Applicable only if LVM is compiled with lvmpolld support.
|
||||
use_lvmpolld = @DEFAULT_USE_LVMPOLLD@
|
||||
|
||||
# Configuration option global/notify_dbus.
|
||||
# Enable D-Bus notification from LVM commands.
|
||||
# When enabled, an LVM command that changes PVs, changes VG metadata,
|
||||
# or changes the activation state of an LV will send a notification.
|
||||
notify_dbus = 1
|
||||
}
|
||||
|
||||
# Configuration section activation.
|
||||
@@ -1520,22 +1426,6 @@ activation {
|
||||
# This configuration option has an automatic default value.
|
||||
# check_pv_device_sizes = 1
|
||||
|
||||
# Configuration option metadata/record_lvs_history.
|
||||
# When enabled, LVM keeps history records about removed LVs in
|
||||
# metadata. The information that is recorded in metadata for
|
||||
# historical LVs is reduced when compared to original
|
||||
# information kept in metadata for live LVs. Currently, this
|
||||
# feature is supported for thin and thin snapshot LVs only.
|
||||
# This configuration option has an automatic default value.
|
||||
# record_lvs_history = 0
|
||||
|
||||
# Configuration option metadata/lvs_history_retention_time.
|
||||
# Retention time in seconds after which a record about individual
|
||||
# historical logical volume is automatically destroyed.
|
||||
# A value of 0 disables this feature.
|
||||
# This configuration option has an automatic default value.
|
||||
# lvs_history_retention_time = 0
|
||||
|
||||
# Configuration option metadata/pvmetadatacopies.
|
||||
# Number of copies of metadata to store on each PV.
|
||||
# The --pvmetadatacopies option overrides this setting.
|
||||
@@ -1614,22 +1504,6 @@ activation {
|
||||
# This configuration section has an automatic default value.
|
||||
# report {
|
||||
|
||||
# Configuration option report/output_format.
|
||||
# Format of LVM command's report output.
|
||||
# If there is more than one report per command, then the format
|
||||
# is applied for all reports. You can also change output format
|
||||
# directly on command line using --reportformat option which
|
||||
# has precedence over log/output_format setting.
|
||||
# Accepted values:
|
||||
# basic
|
||||
# Original format with columns and rows. If there is more than
|
||||
# one report per command, each report is prefixed with report's
|
||||
# name for identification.
|
||||
# json
|
||||
# JSON format.
|
||||
# This configuration option has an automatic default value.
|
||||
# output_format = "basic"
|
||||
|
||||
# Configuration option report/compact_output.
|
||||
# Do not print empty values for all report fields.
|
||||
# If enabled, all fields that don't have a value set for any of the
|
||||
@@ -1690,11 +1564,11 @@ activation {
|
||||
# This configuration option has an automatic default value.
|
||||
# quoted = 1
|
||||
|
||||
# Configuration option report/columns_as_rows.
|
||||
# Configuration option report/colums_as_rows.
|
||||
# Output each column as a row.
|
||||
# If set, this also implies report/prefixes=1.
|
||||
# This configuration option has an automatic default value.
|
||||
# columns_as_rows = 0
|
||||
# colums_as_rows = 0
|
||||
|
||||
# Configuration option report/binary_values_as_numeric.
|
||||
# Use binary values 0 or 1 instead of descriptive literal values.
|
||||
@@ -1946,76 +1820,10 @@ activation {
|
||||
# This configuration option has an automatic default value.
|
||||
# pvsegs_cols_verbose = "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size,lv_name,seg_start_pe,segtype,seg_pe_ranges"
|
||||
|
||||
# Configuration option report/vgs_cols_full.
|
||||
# List of columns to report for lvm fullreport's 'vgs' subreport.
|
||||
# See 'vgs -o help' for the list of possible fields.
|
||||
# This configuration option has an automatic default value.
|
||||
# vgs_cols_full = "vg_all"
|
||||
|
||||
# Configuration option report/pvs_cols_full.
|
||||
# List of columns to report for lvm fullreport's 'vgs' subreport.
|
||||
# See 'pvs -o help' for the list of possible fields.
|
||||
# This configuration option has an automatic default value.
|
||||
# pvs_cols_full = "pv_all"
|
||||
|
||||
# Configuration option report/lvs_cols_full.
|
||||
# List of columns to report for lvm fullreport's 'lvs' subreport.
|
||||
# See 'lvs -o help' for the list of possible fields.
|
||||
# This configuration option has an automatic default value.
|
||||
# lvs_cols_full = "lv_all"
|
||||
|
||||
# Configuration option report/pvsegs_cols_full.
|
||||
# List of columns to report for lvm fullreport's 'pvseg' subreport.
|
||||
# See 'pvs --segments -o help' for the list of possible fields.
|
||||
# This configuration option has an automatic default value.
|
||||
# pvsegs_cols_full = "pvseg_all,pv_uuid,lv_uuid"
|
||||
|
||||
# Configuration option report/segs_cols_full.
|
||||
# List of columns to report for lvm fullreport's 'seg' subreport.
|
||||
# See 'lvs --segments -o help' for the list of possible fields.
|
||||
# This configuration option has an automatic default value.
|
||||
# segs_cols_full = "seg_all,lv_uuid"
|
||||
|
||||
# Configuration option report/vgs_sort_full.
|
||||
# List of columns to sort by when reporting lvm fullreport's 'vgs' subreport.
|
||||
# See 'vgs -o help' for the list of possible fields.
|
||||
# This configuration option has an automatic default value.
|
||||
# vgs_sort_full = "vg_name"
|
||||
|
||||
# Configuration option report/pvs_sort_full.
|
||||
# List of columns to sort by when reporting lvm fullreport's 'vgs' subreport.
|
||||
# See 'pvs -o help' for the list of possible fields.
|
||||
# This configuration option has an automatic default value.
|
||||
# pvs_sort_full = "pv_name"
|
||||
|
||||
# Configuration option report/lvs_sort_full.
|
||||
# List of columns to sort by when reporting lvm fullreport's 'lvs' subreport.
|
||||
# See 'lvs -o help' for the list of possible fields.
|
||||
# This configuration option has an automatic default value.
|
||||
# lvs_sort_full = "vg_name,lv_name"
|
||||
|
||||
# Configuration option report/pvsegs_sort_full.
|
||||
# List of columns to sort by when reporting for lvm fullreport's 'pvseg' subreport.
|
||||
# See 'pvs --segments -o help' for the list of possible fields.
|
||||
# This configuration option has an automatic default value.
|
||||
# pvsegs_sort_full = "pv_uuid,pvseg_start"
|
||||
|
||||
# Configuration option report/segs_sort_full.
|
||||
# List of columns to sort by when reporting lvm fullreport's 'seg' subreport.
|
||||
# See 'lvs --segments -o help' for the list of possible fields.
|
||||
# This configuration option has an automatic default value.
|
||||
# segs_sort_full = "lv_uuid,seg_start"
|
||||
|
||||
# Configuration option report/mark_hidden_devices.
|
||||
# Use brackets [] to mark hidden devices.
|
||||
# This configuration option has an automatic default value.
|
||||
# mark_hidden_devices = 1
|
||||
|
||||
# Configuration option report/two_word_unknown_device.
|
||||
# Use the two words 'unknown device' in place of '[unknown]'.
|
||||
# This is displayed when the device for a PV is not known.
|
||||
# This configuration option has an automatic default value.
|
||||
# two_word_unknown_device = 0
|
||||
# }
|
||||
|
||||
# Configuration section dmeventd.
|
||||
|
@@ -1,50 +0,0 @@
|
||||
#
|
||||
# DO NOT EDIT THIS FILE!
|
||||
#
|
||||
# LVM configuration profile used by lvmdbusd daemon.
|
||||
#
|
||||
# This sets up LVM to produce output in the most suitable format for processing
|
||||
# by lvmdbusd daemon which utilizes LVM shell to execute LVM commands.
|
||||
#
|
||||
# Do not edit this file in any way. This profile is distributed together with
|
||||
# lvmdbusd and it contains configuration that is important for lvmdbusd to
|
||||
# cooperate and interface with LVM correctly.
|
||||
#
|
||||
|
||||
global {
|
||||
# use bytes for expected and deterministic output
|
||||
units=b
|
||||
# no need for suffix if we have units set
|
||||
suffix=0
|
||||
}
|
||||
|
||||
report {
|
||||
compact_output=0
|
||||
compact_output_cols=""
|
||||
binary_values_as_numeric=0
|
||||
# time in number of seconds since the Epoch
|
||||
time_format="%s"
|
||||
mark_hidden_devices=1
|
||||
# lvmdbusd expects JSON output
|
||||
output_format=json
|
||||
# *_cols_full for lvm fullreport's fields which lvmdbusd relies on to update its state
|
||||
vgs_cols_full="vg_name,vg_uuid,vg_fmt,vg_size,vg_free,vg_sysid,vg_extent_size,vg_extent_count,vg_free_count,vg_profile,max_lv,max_pv,pv_count,lv_count,snap_count,vg_seqno,vg_mda_count,vg_mda_free,vg_mda_size,vg_mda_used_count,vg_attr,vg_tags"
|
||||
pvs_cols_full="pv_name,pv_uuid,pv_fmt,pv_size,pv_free,pv_used,dev_size,pv_mda_size,pv_mda_free,pv_ba_start,pv_ba_size,pe_start,pv_pe_count,pv_pe_alloc_count,pv_attr,pv_tags,vg_name,vg_uuid"
|
||||
lvs_cols_full="lv_uuid,lv_name,lv_path,lv_size,vg_name,pool_lv_uuid,pool_lv,origin_uuid,origin,data_percent,lv_attr,lv_tags,vg_uuid,lv_active,data_lv,metadata_lv,lv_parent,lv_role,lv_layout"
|
||||
pvsegs_cols_full="pvseg_start,pvseg_size,segtype,pv_uuid,lv_uuid,pv_name"
|
||||
segs_cols_full="seg_pe_ranges,segtype,lv_uuid"
|
||||
vgs_sort_full="vg_name"
|
||||
pvs_sort_full="pv_name"
|
||||
lvs_sort_full="vg_name,lv_name"
|
||||
pvsegs_sort_full="pv_uuid,pvseg_start"
|
||||
segs_sort_full="lv_uuid,seg_start"
|
||||
}
|
||||
|
||||
log {
|
||||
# lvmdbusd relies on command log report to inspect LVM command's execution status
|
||||
report_command_log=1
|
||||
# display only outermost LVM shell-related log that lvmdbusd inspects first after LVM command execution (it calls 'lastlog' for more detailed log afterwards if needed)
|
||||
command_log_selection="log_context=shell"
|
||||
command_log_cols="log_seq_num,log_type,log_context,log_object_type,log_object_name,log_object_id,log_object_group,log_object_group_id,log_message,log_errno,log_ret_code"
|
||||
command_log_sort="log_seq_num"
|
||||
}
|
@@ -51,7 +51,6 @@ local {
|
||||
# Configuration option local/host_id.
|
||||
# The lvmlockd sanlock host_id.
|
||||
# This must be unique among all hosts, and must be between 1 and 2000.
|
||||
# Applicable only if LVM is compiled with lockd support
|
||||
# This configuration option has an automatic default value.
|
||||
# host_id = 0
|
||||
}
|
||||
|
167
configure
vendored
167
configure
vendored
@@ -676,7 +676,6 @@ PTHREAD_LIBS
|
||||
M_LIBS
|
||||
POOL
|
||||
PKGCONFIG
|
||||
ODIRECT
|
||||
OCFDIR
|
||||
OCF
|
||||
MIRRORS
|
||||
@@ -736,7 +735,6 @@ CLDWHOLEARCHIVE
|
||||
CLDNOWHOLEARCHIVE
|
||||
CLDFLAGS
|
||||
CACHE
|
||||
BUILD_NOTIFYDBUS
|
||||
BUILD_LOCKDDLM
|
||||
BUILD_LOCKDSANLOCK
|
||||
BUILD_LVMLOCKD
|
||||
@@ -769,8 +767,6 @@ SYSTEMD_LIBS
|
||||
SYSTEMD_CFLAGS
|
||||
BLKID_LIBS
|
||||
BLKID_CFLAGS
|
||||
NOTIFY_DBUS_LIBS
|
||||
NOTIFY_DBUS_CFLAGS
|
||||
LOCKD_DLM_LIBS
|
||||
LOCKD_DLM_CFLAGS
|
||||
LOCKD_SANLOCK_LIBS
|
||||
@@ -958,7 +954,6 @@ enable_use_lvmetad
|
||||
with_lvmetad_pidfile
|
||||
enable_use_lvmpolld
|
||||
with_lvmpolld_pidfile
|
||||
enable_notify_dbus
|
||||
enable_blkid_wiping
|
||||
enable_udev_systemd_background_jobs
|
||||
enable_udev_sync
|
||||
@@ -1044,8 +1039,6 @@ LOCKD_SANLOCK_CFLAGS
|
||||
LOCKD_SANLOCK_LIBS
|
||||
LOCKD_DLM_CFLAGS
|
||||
LOCKD_DLM_LIBS
|
||||
NOTIFY_DBUS_CFLAGS
|
||||
NOTIFY_DBUS_LIBS
|
||||
BLKID_CFLAGS
|
||||
BLKID_LIBS
|
||||
SYSTEMD_CFLAGS
|
||||
@@ -1692,7 +1685,6 @@ Optional Features:
|
||||
--disable-use-lvmlockd disable usage of LVM lock daemon
|
||||
--disable-use-lvmetad disable usage of LVM Metadata Daemon
|
||||
--disable-use-lvmpolld disable usage of LVM Poll Daemon
|
||||
--enable-notify-dbus enable LVM notification using dbus
|
||||
--disable-blkid_wiping disable libblkid detection of signatures when wiping
|
||||
and use native code instead
|
||||
--disable-udev-systemd-background-jobs
|
||||
@@ -1821,7 +1813,7 @@ Optional Packages:
|
||||
--with-default-cache-subdir=SUBDIR
|
||||
default metadata cache subdir [cache]
|
||||
--with-default-locking-dir=DIR
|
||||
default locking directory [autodetect_lock_dir/lvm]
|
||||
default locking directory [/var/lock/lvm]
|
||||
--with-default-data-alignment=NUM
|
||||
set the default data alignment in MiB [1]
|
||||
--with-interface=IFACE choose kernel interface (ioctl) [ioctl]
|
||||
@@ -1885,10 +1877,6 @@ Some influential environment variables:
|
||||
C compiler flags for LOCKD_DLM, overriding pkg-config
|
||||
LOCKD_DLM_LIBS
|
||||
linker flags for LOCKD_DLM, overriding pkg-config
|
||||
NOTIFY_DBUS_CFLAGS
|
||||
C compiler flags for NOTIFY_DBUS, overriding pkg-config
|
||||
NOTIFY_DBUS_LIBS
|
||||
linker flags for NOTIFY_DBUS, overriding pkg-config
|
||||
BLKID_CFLAGS
|
||||
C compiler flags for BLKID, overriding pkg-config
|
||||
BLKID_LIBS linker flags for BLKID, overriding pkg-config
|
||||
@@ -3169,8 +3157,8 @@ case "$host_os" in
|
||||
LDDEPS="$LDDEPS .export.sym"
|
||||
LIB_SUFFIX=so
|
||||
DEVMAPPER=yes
|
||||
BUILD_LVMETAD=no
|
||||
BUILD_LVMPOLLD=no
|
||||
LVMETAD=no
|
||||
LVMPOLLD=no
|
||||
LOCKDSANLOCK=no
|
||||
LOCKDDLM=no
|
||||
ODIRECT=yes
|
||||
@@ -5876,7 +5864,7 @@ fi
|
||||
done
|
||||
|
||||
|
||||
for ac_header in termios.h sys/statvfs.h sys/timerfd.h linux/magic.h linux/fiemap.h
|
||||
for ac_header in termios.h sys/statvfs.h sys/timerfd.h
|
||||
do :
|
||||
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
|
||||
@@ -11487,9 +11475,10 @@ if test "${enable_lvmetad+set}" = set; then :
|
||||
enableval=$enable_lvmetad; LVMETAD=$enableval
|
||||
fi
|
||||
|
||||
test -n "$LVMETAD" && BUILD_LVMETAD=$LVMETAD
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_LVMETAD" >&5
|
||||
$as_echo "$BUILD_LVMETAD" >&6; }
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $LVMETAD" >&5
|
||||
$as_echo "$LVMETAD" >&6; }
|
||||
|
||||
BUILD_LVMETAD=$LVMETAD
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build lvmpolld" >&5
|
||||
@@ -11499,9 +11488,10 @@ if test "${enable_lvmpolld+set}" = set; then :
|
||||
enableval=$enable_lvmpolld; LVMPOLLD=$enableval
|
||||
fi
|
||||
|
||||
test -n "$LVMPOLLD" && BUILD_LVMPOLLD=$LVMPOLLD
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_LVMPOLLD" >&5
|
||||
$as_echo "$BUILD_LVMPOLLD" >&6; }
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $LVMPOLLD" >&5
|
||||
$as_echo "$LVMPOLLD" >&6; }
|
||||
|
||||
BUILD_LVMPOLLD=$LVMPOLLD
|
||||
|
||||
################################################################################
|
||||
BUILD_LVMLOCKD=no
|
||||
@@ -11528,12 +11518,12 @@ if test -n "$LOCKD_SANLOCK_CFLAGS"; then
|
||||
pkg_cv_LOCKD_SANLOCK_CFLAGS="$LOCKD_SANLOCK_CFLAGS"
|
||||
elif test -n "$PKG_CONFIG"; then
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsanlock_client >= 3.3.0\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "libsanlock_client >= 3.3.0") 2>&5
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsanlock_client\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "libsanlock_client") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
pkg_cv_LOCKD_SANLOCK_CFLAGS=`$PKG_CONFIG --cflags "libsanlock_client >= 3.3.0" 2>/dev/null`
|
||||
pkg_cv_LOCKD_SANLOCK_CFLAGS=`$PKG_CONFIG --cflags "libsanlock_client" 2>/dev/null`
|
||||
test "x$?" != "x0" && pkg_failed=yes
|
||||
else
|
||||
pkg_failed=yes
|
||||
@@ -11545,12 +11535,12 @@ if test -n "$LOCKD_SANLOCK_LIBS"; then
|
||||
pkg_cv_LOCKD_SANLOCK_LIBS="$LOCKD_SANLOCK_LIBS"
|
||||
elif test -n "$PKG_CONFIG"; then
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsanlock_client >= 3.3.0\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "libsanlock_client >= 3.3.0") 2>&5
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsanlock_client\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "libsanlock_client") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
pkg_cv_LOCKD_SANLOCK_LIBS=`$PKG_CONFIG --libs "libsanlock_client >= 3.3.0" 2>/dev/null`
|
||||
pkg_cv_LOCKD_SANLOCK_LIBS=`$PKG_CONFIG --libs "libsanlock_client" 2>/dev/null`
|
||||
test "x$?" != "x0" && pkg_failed=yes
|
||||
else
|
||||
pkg_failed=yes
|
||||
@@ -11571,9 +11561,9 @@ else
|
||||
_pkg_short_errors_supported=no
|
||||
fi
|
||||
if test $_pkg_short_errors_supported = yes; then
|
||||
LOCKD_SANLOCK_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsanlock_client >= 3.3.0" 2>&1`
|
||||
LOCKD_SANLOCK_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsanlock_client" 2>&1`
|
||||
else
|
||||
LOCKD_SANLOCK_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsanlock_client >= 3.3.0" 2>&1`
|
||||
LOCKD_SANLOCK_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsanlock_client" 2>&1`
|
||||
fi
|
||||
# Put the nasty error message in config.log where it belongs
|
||||
echo "$LOCKD_SANLOCK_PKG_ERRORS" >&5
|
||||
@@ -11694,17 +11684,11 @@ $as_echo_n "checking whether to build lvmlockd... " >&6; }
|
||||
$as_echo "$BUILD_LVMLOCKD" >&6; }
|
||||
|
||||
if test "$BUILD_LVMLOCKD" = yes; then
|
||||
if test "$LVMPOLLD" = no; then :
|
||||
as_fn_error $? "cannot build lvmlockd with --disable-lvmpolld." "$LINENO" 5
|
||||
fi
|
||||
if test "$LVMETAD" = no; then :
|
||||
as_fn_error $? "cannot build lvmlockd with --disable-lvmetad." "$LINENO" 5
|
||||
fi
|
||||
if test "$BUILD_LVMPOLLD" = no; then :
|
||||
if test -n "$BUILD_LVMPOLLD"; then :
|
||||
BUILD_LVMPOLLD=yes; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Enabling lvmpolld - required by lvmlockd." >&5
|
||||
$as_echo "$as_me: WARNING: Enabling lvmpolld - required by lvmlockd." >&2;}
|
||||
fi
|
||||
if test "$BUILD_LVMETAD" = no; then :
|
||||
if test -n "$BUILD_LVMETAD"; then :
|
||||
BUILD_LVMETAD=yes; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Enabling lvmetad - required by lvmlockd." >&5
|
||||
$as_echo "$as_me: WARNING: Enabling lvmetad - required by lvmlockd." >&2;}
|
||||
fi
|
||||
@@ -11832,101 +11816,6 @@ cat >>confdefs.h <<_ACEOF
|
||||
_ACEOF
|
||||
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build notifydbus" >&5
|
||||
$as_echo_n "checking whether to build notifydbus... " >&6; }
|
||||
# Check whether --enable-notify-dbus was given.
|
||||
if test "${enable_notify_dbus+set}" = set; then :
|
||||
enableval=$enable_notify_dbus; NOTIFYDBUS=$enableval
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $NOTIFYDBUS" >&5
|
||||
$as_echo "$NOTIFYDBUS" >&6; }
|
||||
|
||||
BUILD_NOTIFYDBUS=$NOTIFYDBUS
|
||||
|
||||
if test "$BUILD_NOTIFYDBUS" = yes; then
|
||||
|
||||
$as_echo "#define NOTIFYDBUS_SUPPORT 1" >>confdefs.h
|
||||
|
||||
LIBS="-lsystemd $LIBS"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
if test "$BUILD_NOTIFYDBUS" = yes; then
|
||||
|
||||
pkg_failed=no
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for NOTIFY_DBUS" >&5
|
||||
$as_echo_n "checking for NOTIFY_DBUS... " >&6; }
|
||||
|
||||
if test -n "$NOTIFY_DBUS_CFLAGS"; then
|
||||
pkg_cv_NOTIFY_DBUS_CFLAGS="$NOTIFY_DBUS_CFLAGS"
|
||||
elif test -n "$PKG_CONFIG"; then
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"systemd >= 221\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "systemd >= 221") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
pkg_cv_NOTIFY_DBUS_CFLAGS=`$PKG_CONFIG --cflags "systemd >= 221" 2>/dev/null`
|
||||
test "x$?" != "x0" && pkg_failed=yes
|
||||
else
|
||||
pkg_failed=yes
|
||||
fi
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi
|
||||
if test -n "$NOTIFY_DBUS_LIBS"; then
|
||||
pkg_cv_NOTIFY_DBUS_LIBS="$NOTIFY_DBUS_LIBS"
|
||||
elif test -n "$PKG_CONFIG"; then
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"systemd >= 221\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "systemd >= 221") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
pkg_cv_NOTIFY_DBUS_LIBS=`$PKG_CONFIG --libs "systemd >= 221" 2>/dev/null`
|
||||
test "x$?" != "x0" && pkg_failed=yes
|
||||
else
|
||||
pkg_failed=yes
|
||||
fi
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi
|
||||
|
||||
|
||||
|
||||
if test $pkg_failed = yes; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||
_pkg_short_errors_supported=yes
|
||||
else
|
||||
_pkg_short_errors_supported=no
|
||||
fi
|
||||
if test $_pkg_short_errors_supported = yes; then
|
||||
NOTIFY_DBUS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "systemd >= 221" 2>&1`
|
||||
else
|
||||
NOTIFY_DBUS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "systemd >= 221" 2>&1`
|
||||
fi
|
||||
# Put the nasty error message in config.log where it belongs
|
||||
echo "$NOTIFY_DBUS_PKG_ERRORS" >&5
|
||||
|
||||
$bailout
|
||||
elif test $pkg_failed = untried; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
$bailout
|
||||
else
|
||||
NOTIFY_DBUS_CFLAGS=$pkg_cv_NOTIFY_DBUS_CFLAGS
|
||||
NOTIFY_DBUS_LIBS=$pkg_cv_NOTIFY_DBUS_LIBS
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
HAVE_NOTIFY_DBUS=yes
|
||||
fi
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable libblkid detection of signatures when wiping" >&5
|
||||
@@ -15118,12 +15007,7 @@ _ACEOF
|
||||
if test "${with_default_locking_dir+set}" = set; then :
|
||||
withval=$with_default_locking_dir; DEFAULT_LOCK_DIR=$withval
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for default lock directory" >&5
|
||||
$as_echo_n "checking for default lock directory... " >&6; }
|
||||
DEFAULT_LOCK_DIR="$RUN_DIR/lock/lvm"
|
||||
test -d "$RUN_DIR/lock" || DEFAULT_LOCK_DIR="/var/lock/lvm"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $DEFAULT_LOCK_DIR" >&5
|
||||
$as_echo "$DEFAULT_LOCK_DIR" >&6; }
|
||||
DEFAULT_LOCK_DIR="/var/lock/lvm"
|
||||
fi
|
||||
|
||||
|
||||
@@ -15338,13 +15222,11 @@ LVM_LIBAPI=`echo "$VER" | $AWK -F '[()]' '{print $2}'`
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
################################################################################
|
||||
ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile daemons/dmeventd/plugins/thin/Makefile daemons/lvmdbusd/Makefile daemons/lvmdbusd/path.py daemons/lvmetad/Makefile daemons/lvmpolld/Makefile daemons/lvmlockd/Makefile conf/Makefile conf/example.conf conf/lvmlocal.conf conf/command_profile_template.profile conf/metadata_profile_template.profile include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile include/lvm-version.h lib/raid/Makefile lib/snapshot/Makefile lib/thin/Makefile lib/cache_segtype/Makefile libdaemon/Makefile libdaemon/client/Makefile libdaemon/server/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile python/Makefile python/setup.py scripts/blkdeactivate.sh scripts/blk_availability_init_red_hat scripts/blk_availability_systemd_red_hat.service scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/com.redhat.lvmdbus1.service scripts/dm_event_systemd_red_hat.service scripts/dm_event_systemd_red_hat.socket scripts/lvm2_cluster_activation_red_hat.sh scripts/lvm2_cluster_activation_systemd_red_hat.service scripts/lvm2_clvmd_systemd_red_hat.service scripts/lvm2_cmirrord_systemd_red_hat.service scripts/lvm2_lvmdbusd_systemd_red_hat.service scripts/lvm2_lvmetad_init_red_hat scripts/lvm2_lvmetad_systemd_red_hat.service scripts/lvm2_lvmetad_systemd_red_hat.socket scripts/lvm2_lvmpolld_init_red_hat scripts/lvm2_lvmpolld_systemd_red_hat.service scripts/lvm2_lvmpolld_systemd_red_hat.socket scripts/lvm2_lvmlockd_systemd_red_hat.service scripts/lvm2_lvmlocking_systemd_red_hat.service scripts/lvm2_monitoring_init_red_hat scripts/lvm2_monitoring_systemd_red_hat.service scripts/lvm2_pvscan_systemd_red_hat@.service scripts/lvm2_tmpfiles_red_hat.conf scripts/lvmdump.sh scripts/Makefile test/Makefile test/api/Makefile test/unit/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile"
|
||||
ac_config_files="$ac_config_files Makefile make.tmpl daemons/Makefile daemons/clvmd/Makefile daemons/cmirrord/Makefile daemons/dmeventd/Makefile daemons/dmeventd/libdevmapper-event.pc daemons/dmeventd/plugins/Makefile daemons/dmeventd/plugins/lvm2/Makefile daemons/dmeventd/plugins/raid/Makefile daemons/dmeventd/plugins/mirror/Makefile daemons/dmeventd/plugins/snapshot/Makefile daemons/dmeventd/plugins/thin/Makefile daemons/lvmdbusd/Makefile daemons/lvmdbusd/path.py daemons/lvmetad/Makefile daemons/lvmpolld/Makefile daemons/lvmlockd/Makefile conf/Makefile conf/example.conf conf/lvmlocal.conf conf/command_profile_template.profile conf/metadata_profile_template.profile include/.symlinks include/Makefile lib/Makefile lib/format1/Makefile lib/format_pool/Makefile lib/locking/Makefile lib/mirror/Makefile lib/replicator/Makefile include/lvm-version.h lib/raid/Makefile lib/snapshot/Makefile lib/thin/Makefile lib/cache_segtype/Makefile libdaemon/Makefile libdaemon/client/Makefile libdaemon/server/Makefile libdm/Makefile libdm/libdevmapper.pc liblvm/Makefile liblvm/liblvm2app.pc man/Makefile po/Makefile python/Makefile python/setup.py scripts/blkdeactivate.sh scripts/blk_availability_init_red_hat scripts/blk_availability_systemd_red_hat.service scripts/clvmd_init_red_hat scripts/cmirrord_init_red_hat scripts/com.redhat.lvmdbus1.service scripts/dm_event_systemd_red_hat.service scripts/dm_event_systemd_red_hat.socket scripts/lvm2_cluster_activation_red_hat.sh scripts/lvm2_cluster_activation_systemd_red_hat.service scripts/lvm2_clvmd_systemd_red_hat.service scripts/lvm2_cmirrord_systemd_red_hat.service scripts/lvm2_lvmdbusd_systemd_red_hat.service scripts/lvm2_lvmetad_init_red_hat scripts/lvm2_lvmetad_systemd_red_hat.service scripts/lvm2_lvmetad_systemd_red_hat.socket scripts/lvm2_lvmpolld_init_red_hat scripts/lvm2_lvmpolld_systemd_red_hat.service scripts/lvm2_lvmpolld_systemd_red_hat.socket scripts/lvm2_lvmlockd_systemd_red_hat.service scripts/lvm2_lvmlocking_systemd_red_hat.service scripts/lvm2_monitoring_init_red_hat scripts/lvm2_monitoring_systemd_red_hat.service scripts/lvm2_pvscan_systemd_red_hat@.service scripts/lvm2_tmpfiles_red_hat.conf scripts/Makefile test/Makefile test/api/Makefile test/unit/Makefile tools/Makefile udev/Makefile unit-tests/datastruct/Makefile unit-tests/regex/Makefile unit-tests/mm/Makefile"
|
||||
|
||||
cat >confcache <<\_ACEOF
|
||||
# This file is a shell script that caches the results of configure
|
||||
@@ -16111,7 +15993,6 @@ do
|
||||
"scripts/lvm2_monitoring_systemd_red_hat.service") CONFIG_FILES="$CONFIG_FILES scripts/lvm2_monitoring_systemd_red_hat.service" ;;
|
||||
"scripts/lvm2_pvscan_systemd_red_hat@.service") CONFIG_FILES="$CONFIG_FILES scripts/lvm2_pvscan_systemd_red_hat@.service" ;;
|
||||
"scripts/lvm2_tmpfiles_red_hat.conf") CONFIG_FILES="$CONFIG_FILES scripts/lvm2_tmpfiles_red_hat.conf" ;;
|
||||
"scripts/lvmdump.sh") CONFIG_FILES="$CONFIG_FILES scripts/lvmdump.sh" ;;
|
||||
"scripts/Makefile") CONFIG_FILES="$CONFIG_FILES scripts/Makefile" ;;
|
||||
"test/Makefile") CONFIG_FILES="$CONFIG_FILES test/Makefile" ;;
|
||||
"test/api/Makefile") CONFIG_FILES="$CONFIG_FILES test/api/Makefile" ;;
|
||||
|
57
configure.in
57
configure.in
@@ -37,8 +37,8 @@ case "$host_os" in
|
||||
LDDEPS="$LDDEPS .export.sym"
|
||||
LIB_SUFFIX=so
|
||||
DEVMAPPER=yes
|
||||
BUILD_LVMETAD=no
|
||||
BUILD_LVMPOLLD=no
|
||||
LVMETAD=no
|
||||
LVMPOLLD=no
|
||||
LOCKDSANLOCK=no
|
||||
LOCKDDLM=no
|
||||
ODIRECT=yes
|
||||
@@ -103,7 +103,7 @@ AC_CHECK_HEADERS([assert.h ctype.h dirent.h errno.h fcntl.h float.h \
|
||||
sys/time.h sys/types.h sys/utsname.h sys/wait.h time.h \
|
||||
unistd.h], , [AC_MSG_ERROR(bailing out)])
|
||||
|
||||
AC_CHECK_HEADERS(termios.h sys/statvfs.h sys/timerfd.h linux/magic.h linux/fiemap.h)
|
||||
AC_CHECK_HEADERS(termios.h sys/statvfs.h sys/timerfd.h)
|
||||
|
||||
case "$host_os" in
|
||||
linux*)
|
||||
@@ -1129,8 +1129,9 @@ AC_ARG_ENABLE(lvmetad,
|
||||
AC_HELP_STRING([--enable-lvmetad],
|
||||
[enable the LVM Metadata Daemon]),
|
||||
LVMETAD=$enableval)
|
||||
test -n "$LVMETAD" && BUILD_LVMETAD=$LVMETAD
|
||||
AC_MSG_RESULT($BUILD_LVMETAD)
|
||||
AC_MSG_RESULT($LVMETAD)
|
||||
|
||||
BUILD_LVMETAD=$LVMETAD
|
||||
|
||||
################################################################################
|
||||
dnl -- Build lvmpolld
|
||||
@@ -1139,8 +1140,9 @@ AC_ARG_ENABLE(lvmpolld,
|
||||
AC_HELP_STRING([--enable-lvmpolld],
|
||||
[enable the LVM Polling Daemon]),
|
||||
LVMPOLLD=$enableval)
|
||||
test -n "$LVMPOLLD" && BUILD_LVMPOLLD=$LVMPOLLD
|
||||
AC_MSG_RESULT($BUILD_LVMPOLLD)
|
||||
AC_MSG_RESULT($LVMPOLLD)
|
||||
|
||||
BUILD_LVMPOLLD=$LVMPOLLD
|
||||
|
||||
################################################################################
|
||||
BUILD_LVMLOCKD=no
|
||||
@@ -1157,7 +1159,7 @@ BUILD_LOCKDSANLOCK=$LOCKDSANLOCK
|
||||
|
||||
dnl -- Look for sanlock libraries
|
||||
if test "$BUILD_LOCKDSANLOCK" = yes; then
|
||||
PKG_CHECK_MODULES(LOCKD_SANLOCK, libsanlock_client >= 3.3.0, [HAVE_LOCKD_SANLOCK=yes], $bailout)
|
||||
PKG_CHECK_MODULES(LOCKD_SANLOCK, libsanlock_client, [HAVE_LOCKD_SANLOCK=yes], $bailout)
|
||||
AC_DEFINE([LOCKDSANLOCK_SUPPORT], 1, [Define to 1 to include code that uses lvmlockd sanlock option.])
|
||||
BUILD_LVMLOCKD=yes
|
||||
fi
|
||||
@@ -1186,10 +1188,8 @@ AC_MSG_CHECKING(whether to build lvmlockd)
|
||||
AC_MSG_RESULT($BUILD_LVMLOCKD)
|
||||
|
||||
if test "$BUILD_LVMLOCKD" = yes; then
|
||||
AS_IF([test "$LVMPOLLD" = no], [AC_MSG_ERROR([cannot build lvmlockd with --disable-lvmpolld.])])
|
||||
AS_IF([test "$LVMETAD" = no], [AC_MSG_ERROR([cannot build lvmlockd with --disable-lvmetad.])])
|
||||
AS_IF([test "$BUILD_LVMPOLLD" = no], [BUILD_LVMPOLLD=yes; AC_MSG_WARN([Enabling lvmpolld - required by lvmlockd.])])
|
||||
AS_IF([test "$BUILD_LVMETAD" = no], [BUILD_LVMETAD=yes; AC_MSG_WARN([Enabling lvmetad - required by lvmlockd.])])
|
||||
AS_IF([test -n "$BUILD_LVMPOLLD"], [BUILD_LVMPOLLD=yes; AC_MSG_WARN([Enabling lvmpolld - required by lvmlockd.])])
|
||||
AS_IF([test -n "$BUILD_LVMETAD"], [BUILD_LVMETAD=yes; AC_MSG_WARN([Enabling lvmetad - required by lvmlockd.])])
|
||||
AC_MSG_CHECKING([defaults for use_lvmlockd])
|
||||
AC_ARG_ENABLE(use_lvmlockd,
|
||||
AC_HELP_STRING([--disable-use-lvmlockd],
|
||||
@@ -1268,28 +1268,6 @@ fi
|
||||
AC_DEFINE_UNQUOTED(DEFAULT_USE_LVMPOLLD, [$DEFAULT_USE_LVMPOLLD],
|
||||
[Use lvmpolld by default.])
|
||||
|
||||
################################################################################
|
||||
dnl -- Build notifydbus
|
||||
AC_MSG_CHECKING(whether to build notifydbus)
|
||||
AC_ARG_ENABLE(notify-dbus,
|
||||
AC_HELP_STRING([--enable-notify-dbus],
|
||||
[enable LVM notification using dbus]),
|
||||
NOTIFYDBUS=$enableval)
|
||||
AC_MSG_RESULT($NOTIFYDBUS)
|
||||
|
||||
BUILD_NOTIFYDBUS=$NOTIFYDBUS
|
||||
|
||||
if test "$BUILD_NOTIFYDBUS" = yes; then
|
||||
AC_DEFINE([NOTIFYDBUS_SUPPORT], 1, [Define to 1 to include code that uses dbus notification.])
|
||||
LIBS="-lsystemd $LIBS"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Look for dbus libraries
|
||||
if test "$BUILD_NOTIFYDBUS" = yes; then
|
||||
PKG_CHECK_MODULES(NOTIFY_DBUS, systemd >= 221, [HAVE_NOTIFY_DBUS=yes], $bailout)
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
|
||||
dnl -- Enable blkid wiping functionality
|
||||
@@ -1933,12 +1911,8 @@ AC_DEFINE_UNQUOTED(DEFAULT_CACHE_SUBDIR, ["$DEFAULT_CACHE_SUBDIR"],
|
||||
|
||||
AC_ARG_WITH(default-locking-dir,
|
||||
AC_HELP_STRING([--with-default-locking-dir=DIR],
|
||||
[default locking directory [autodetect_lock_dir/lvm]]),
|
||||
DEFAULT_LOCK_DIR=$withval,
|
||||
[AC_MSG_CHECKING(for default lock directory)
|
||||
DEFAULT_LOCK_DIR="$RUN_DIR/lock/lvm"
|
||||
test -d "$RUN_DIR/lock" || DEFAULT_LOCK_DIR="/var/lock/lvm"
|
||||
AC_MSG_RESULT($DEFAULT_LOCK_DIR)])
|
||||
[default locking directory [/var/lock/lvm]]),
|
||||
DEFAULT_LOCK_DIR=$withval, DEFAULT_LOCK_DIR="/var/lock/lvm")
|
||||
AC_DEFINE_UNQUOTED(DEFAULT_LOCK_DIR, ["$DEFAULT_LOCK_DIR"],
|
||||
[Name of default locking directory.])
|
||||
|
||||
@@ -1991,7 +1965,6 @@ AC_SUBST(BUILD_LVMPOLLD)
|
||||
AC_SUBST(BUILD_LVMLOCKD)
|
||||
AC_SUBST(BUILD_LOCKDSANLOCK)
|
||||
AC_SUBST(BUILD_LOCKDDLM)
|
||||
AC_SUBST(BUILD_NOTIFYDBUS)
|
||||
AC_SUBST(CACHE)
|
||||
AC_SUBST(CFLAGS)
|
||||
AC_SUBST(CFLOW_CMD)
|
||||
@@ -2068,7 +2041,6 @@ AC_SUBST(MIRRORS)
|
||||
AC_SUBST(MSGFMT)
|
||||
AC_SUBST(OCF)
|
||||
AC_SUBST(OCFDIR)
|
||||
AC_SUBST(ODIRECT)
|
||||
AC_SUBST(PKGCONFIG)
|
||||
AC_SUBST(POOL)
|
||||
AC_SUBST(M_LIBS)
|
||||
@@ -2214,7 +2186,6 @@ scripts/lvm2_monitoring_init_red_hat
|
||||
scripts/lvm2_monitoring_systemd_red_hat.service
|
||||
scripts/lvm2_pvscan_systemd_red_hat@.service
|
||||
scripts/lvm2_tmpfiles_red_hat.conf
|
||||
scripts/lvmdump.sh
|
||||
scripts/Makefile
|
||||
test/Makefile
|
||||
test/api/Makefile
|
||||
|
@@ -50,7 +50,7 @@ struct clvm_header {
|
||||
#define CLVMD_FLAG_REMOTE 8 /* Do this on all nodes except for the local node */
|
||||
|
||||
/* Name of the local socket to communicate between lvm and clvmd */
|
||||
#define CLVMD_SOCKNAME DEFAULT_RUN_DIR "/clvmd.sock"
|
||||
static const char CLVMD_SOCKNAME[]= DEFAULT_RUN_DIR "/clvmd.sock";
|
||||
|
||||
/* Internal commands & replies */
|
||||
#define CLVMD_CMD_REPLY 1
|
||||
|
@@ -1440,7 +1440,7 @@ static void cpg_leave_callback(struct clog_cpg *match,
|
||||
free(rq);
|
||||
}
|
||||
}
|
||||
for (i = 0, j = 0; (int) i < match->checkpoints_needed; i++, j++) {
|
||||
for (i = 0, j = 0; i < match->checkpoints_needed; i++, j++) {
|
||||
match->checkpoint_requesters[j] = match->checkpoint_requesters[i];
|
||||
if (match->checkpoint_requesters[i] == left->nodeid) {
|
||||
LOG_ERROR("[%s] Removing pending ckpt from needed list (%u is leaving)",
|
||||
|
@@ -12,7 +12,6 @@
|
||||
#include "logging.h"
|
||||
#include "functions.h"
|
||||
|
||||
#include <sys/sysmacros.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
@@ -574,12 +573,6 @@ static int clog_ctr(struct dm_ulog_request *rq)
|
||||
for (argc = 0, p = rq->data; (p = strstr(p, " ")); p++, argc++)
|
||||
*p = '\0';
|
||||
|
||||
if (!argc) {
|
||||
LOG_ERROR("Received constructor request with bad data %s",
|
||||
rq->data);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
argv = malloc(argc * sizeof(char *));
|
||||
if (!argv)
|
||||
return -ENOMEM;
|
||||
|
@@ -829,6 +829,17 @@ static void _print_sigset(const char *prefix, const sigset_t *sigset)
|
||||
}
|
||||
#endif
|
||||
|
||||
static sigset_t _unblock_sigalrm(void)
|
||||
{
|
||||
sigset_t set, old;
|
||||
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, SIGALRM);
|
||||
pthread_sigmask(SIG_UNBLOCK, &set, &old);
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
enum {
|
||||
DM_WAIT_RETRY,
|
||||
DM_WAIT_INTR,
|
||||
@@ -838,7 +849,7 @@ enum {
|
||||
/* Wait on a device until an event occurs. */
|
||||
static int _event_wait(struct thread_status *thread)
|
||||
{
|
||||
sigset_t set, old;
|
||||
sigset_t set;
|
||||
int ret = DM_WAIT_RETRY;
|
||||
struct dm_info info;
|
||||
|
||||
@@ -848,12 +859,7 @@ static int _event_wait(struct thread_status *thread)
|
||||
* This is so that you can break out of waiting on an event,
|
||||
* either for a timeout event, or to cancel the thread.
|
||||
*/
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, SIGALRM);
|
||||
if (pthread_sigmask(SIG_UNBLOCK, &set, &old) != 0) {
|
||||
log_sys_error("pthread_sigmask", "unblock alarm");
|
||||
return ret; /* What better */
|
||||
}
|
||||
set = _unblock_sigalrm();
|
||||
|
||||
if (dm_task_run(thread->wait_task)) {
|
||||
thread->current_events |= DM_EVENT_DEVICE_ERROR;
|
||||
@@ -877,11 +883,10 @@ static int _event_wait(struct thread_status *thread)
|
||||
}
|
||||
}
|
||||
|
||||
if (pthread_sigmask(SIG_SETMASK, &old, NULL) != 0)
|
||||
log_sys_error("pthread_sigmask", "block alarm");
|
||||
pthread_sigmask(SIG_SETMASK, &set, NULL);
|
||||
|
||||
#ifdef DEBUG_SIGNALS
|
||||
_print_sigset("dmeventd blocking ", &old);
|
||||
_print_sigset("dmeventd blocking ", &set);
|
||||
#endif
|
||||
DEBUGLOG("Completed waitevent task for %s.", thread->device.name);
|
||||
|
||||
|
@@ -855,9 +855,9 @@ int dm_event_get_version(struct dm_event_fifos *fifos, int *version) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void dm_event_log_set(int debug_log_level, int use_syslog)
|
||||
void dm_event_log_set(int debug_level, int use_syslog)
|
||||
{
|
||||
_debug_level = debug_log_level;
|
||||
_debug_level = debug_level;
|
||||
_use_syslog = use_syslog;
|
||||
}
|
||||
|
||||
|
@@ -106,7 +106,7 @@ int dm_event_register_handler(const struct dm_event_handler *dmevh);
|
||||
int dm_event_unregister_handler(const struct dm_event_handler *dmevh);
|
||||
|
||||
/* Set debug level for logging, and whether to log on stdout/stderr or syslog */
|
||||
void dm_event_log_set(int debug_log_level, int use_syslog);
|
||||
void dm_event_log_set(int debug_level, int use_syslog);
|
||||
|
||||
/* Log messages acroding to current debug level */
|
||||
__attribute__((format(printf, 6, 0)))
|
||||
|
@@ -15,7 +15,7 @@
|
||||
#include "lib.h"
|
||||
#include "libdevmapper-event.h"
|
||||
#include "dmeventd_lvm.h"
|
||||
#include "activate.h" /* For TARGET_NAME* */
|
||||
#include "defaults.h"
|
||||
|
||||
/* FIXME Reformat to 80 char lines. */
|
||||
|
||||
@@ -138,7 +138,7 @@ void process_event(struct dm_task *dmt,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(target_type, TARGET_NAME_MIRROR)) {
|
||||
if (strcmp(target_type, "mirror")) {
|
||||
log_info("%s has unmirrored portion.", device);
|
||||
continue;
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2016 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2005-2015 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@@ -13,20 +13,14 @@
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
#include "defaults.h"
|
||||
#include "dmeventd_lvm.h"
|
||||
#include "libdevmapper-event.h"
|
||||
|
||||
/* Hold enough elements for the mximum number of RAID images */
|
||||
#define RAID_DEVS_ELEMS ((DEFAULT_RAID_MAX_IMAGES + 63) / 64)
|
||||
|
||||
struct dso_state {
|
||||
struct dm_pool *mem;
|
||||
char cmd_lvscan[512];
|
||||
char cmd_lvconvert[512];
|
||||
uint64_t raid_devs[RAID_DEVS_ELEMS];
|
||||
int failed;
|
||||
int warned;
|
||||
};
|
||||
|
||||
DM_EVENT_LOG_FN("raid")
|
||||
@@ -37,39 +31,20 @@ static int _process_raid_event(struct dso_state *state, char *params, const char
|
||||
{
|
||||
struct dm_status_raid *status;
|
||||
const char *d;
|
||||
int dead = 0, r = 1;
|
||||
|
||||
if (!dm_get_status_raid(state->mem, params, &status)) {
|
||||
log_error("Failed to process status line for %s.", device);
|
||||
return 0;
|
||||
}
|
||||
|
||||
d = status->dev_health;
|
||||
while ((d = strchr(d, 'D'))) {
|
||||
uint32_t dev = (uint32_t)(d - status->dev_health);
|
||||
|
||||
if (!(state->raid_devs[dev / 64] & (UINT64_C(1) << (dev % 64))))
|
||||
log_error("Device #%u of %s array, %s, has failed.",
|
||||
dev, status->raid_type, device);
|
||||
|
||||
state->raid_devs[dev / 64] |= (UINT64_C(1) << (dev % 64));
|
||||
d++;
|
||||
dead = 1;
|
||||
}
|
||||
|
||||
if (dead) {
|
||||
if (status->insync_regions < status->total_regions) {
|
||||
if (!state->warned)
|
||||
log_warn("WARNING: waiting for resynchronization to finish "
|
||||
"before initiating repair on RAID device %s", device);
|
||||
|
||||
state->warned = 1;
|
||||
goto out; /* Not yet done syncing with accessible devices */
|
||||
}
|
||||
|
||||
if ((d = strchr(status->dev_health, 'D'))) {
|
||||
if (state->failed)
|
||||
goto out; /* already reported */
|
||||
|
||||
log_error("Device #%d of %s array, %s, has failed.",
|
||||
(int)(d - status->dev_health),
|
||||
status->raid_type, device);
|
||||
|
||||
state->failed = 1;
|
||||
if (!dmeventd_lvm2_run_with_lock(state->cmd_lvscan))
|
||||
log_warn("WARNING: Re-scan of RAID device %s failed.", device);
|
||||
@@ -77,7 +52,8 @@ static int _process_raid_event(struct dso_state *state, char *params, const char
|
||||
/* if repair goes OK, report success even if lvscan has failed */
|
||||
if (!dmeventd_lvm2_run_with_lock(state->cmd_lvconvert)) {
|
||||
log_info("Repair of RAID device %s failed.", device);
|
||||
r = 0;
|
||||
dm_pool_free(state->mem, status);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
state->failed = 0;
|
||||
@@ -88,7 +64,7 @@ static int _process_raid_event(struct dso_state *state, char *params, const char
|
||||
out:
|
||||
dm_pool_free(state->mem, status);
|
||||
|
||||
return r;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt,
|
||||
|
@@ -16,7 +16,6 @@
|
||||
#include "dmeventd_lvm.h"
|
||||
#include "libdevmapper-event.h"
|
||||
|
||||
#include <sys/sysmacros.h>
|
||||
#include <sys/wait.h>
|
||||
#include <stdarg.h>
|
||||
#include <pthread.h>
|
||||
@@ -149,8 +148,8 @@ static void _umount(const char *device, int major, int minor)
|
||||
continue; /* can't stat, skip this one */
|
||||
|
||||
if (S_ISBLK(st.st_mode) &&
|
||||
(int) major(st.st_rdev) == major &&
|
||||
(int) minor(st.st_rdev) == minor) {
|
||||
major(st.st_rdev) == major &&
|
||||
minor(st.st_rdev) == minor) {
|
||||
log_error("Unmounting invalid snapshot %s from %s.", device, words[1]);
|
||||
if (!_run(UMOUNT_COMMAND, "-fl", words[1], NULL))
|
||||
log_error("Failed to umount snapshot %s from %s: %s.",
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2016 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2011-2015 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@@ -30,9 +30,6 @@
|
||||
|
||||
/* First warning when thin data or metadata is 80% full. */
|
||||
#define WARNING_THRESH (DM_PERCENT_1 * 80)
|
||||
/* Umount thin LVs when thin data or metadata LV is >=
|
||||
* and lvextend --use-policies has failed. */
|
||||
#define UMOUNT_THRESH (DM_PERCENT_1 * 95)
|
||||
/* Run a check every 5%. */
|
||||
#define CHECK_STEP (DM_PERCENT_1 * 5)
|
||||
/* Do not bother checking thin data or metadata is less than 50% full. */
|
||||
@@ -56,53 +53,6 @@ struct dso_state {
|
||||
|
||||
DM_EVENT_LOG_FN("thin")
|
||||
|
||||
#define UUID_PREFIX "LVM-"
|
||||
|
||||
/* Figure out device UUID has LVM- prefix and is OPEN */
|
||||
static int _has_unmountable_prefix(int major, int minor)
|
||||
{
|
||||
struct dm_task *dmt;
|
||||
struct dm_info info;
|
||||
const char *uuid;
|
||||
int r = 0;
|
||||
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
|
||||
return_0;
|
||||
|
||||
if (!dm_task_set_major_minor(dmt, major, minor, 1))
|
||||
goto_out;
|
||||
|
||||
if (!dm_task_no_flush(dmt))
|
||||
stack;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
goto out;
|
||||
|
||||
if (!dm_task_get_info(dmt, &info))
|
||||
goto out;
|
||||
|
||||
if (!info.exists || !info.open_count)
|
||||
goto out; /* Not open -> not mounted */
|
||||
|
||||
if (!(uuid = dm_task_get_uuid(dmt)))
|
||||
goto out;
|
||||
|
||||
/* Check it's public mountable LV
|
||||
* has prefix LVM- and UUID size is 68 chars */
|
||||
if (memcmp(uuid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1) ||
|
||||
strlen(uuid) != 68)
|
||||
goto out;
|
||||
|
||||
#if THIN_DEBUG
|
||||
log_debug("Found logical volume %s (%u:%u).", uuid, major, minor);
|
||||
#endif
|
||||
r = 1;
|
||||
out:
|
||||
dm_task_destroy(dmt);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Get dependencies for device, and try to find matching device */
|
||||
static int _has_deps(const char *name, int tp_major, int tp_minor, int *dev_minor)
|
||||
{
|
||||
@@ -140,9 +90,6 @@ static int _has_deps(const char *name, int tp_major, int tp_minor, int *dev_mino
|
||||
|
||||
*dev_minor = info.minor;
|
||||
|
||||
if (!_has_unmountable_prefix(major, info.minor))
|
||||
goto out;
|
||||
|
||||
#if THIN_DEBUG
|
||||
{
|
||||
char dev_name[PATH_MAX];
|
||||
@@ -246,25 +193,20 @@ static int _umount_device(char *buffer, unsigned major, unsigned minor,
|
||||
char *target, void *cb_data)
|
||||
{
|
||||
struct mountinfo_s *data = cb_data;
|
||||
char *words[10];
|
||||
|
||||
if ((major == data->info.major) && dm_bit(data->minors, minor)) {
|
||||
if (dm_split_words(buffer, DM_ARRAY_SIZE(words), 0, words) < DM_ARRAY_SIZE(words))
|
||||
words[9] = NULL; /* just don't show device name */
|
||||
log_info("Unmounting thin %s (%d:%d) of thin pool %s (%u:%u) from mount point \"%s\".",
|
||||
words[9] ? : "", major, minor, data->device,
|
||||
data->info.major, data->info.minor,
|
||||
target);
|
||||
log_info("Unmounting thin volume %s from %s.",
|
||||
data->device, target);
|
||||
if (!_run(UMOUNT_COMMAND, "-fl", target, NULL))
|
||||
log_error("Failed to lazy umount thin %s (%d:%d) from %s: %s.",
|
||||
words[9], major, minor, target, strerror(errno));
|
||||
log_error("Failed to umount thin %s from %s: %s.",
|
||||
data->device, target, strerror(errno));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find all thin pool LV users and try to umount them.
|
||||
* Find all thin pool users and try to umount them.
|
||||
* TODO: work with read-only thin pool support
|
||||
*/
|
||||
static void _umount(struct dm_task *dmt)
|
||||
@@ -298,7 +240,7 @@ out:
|
||||
dm_bitset_destroy(data.minors);
|
||||
}
|
||||
|
||||
static int _use_policy(struct dm_task *dmt, struct dso_state *state)
|
||||
static void _use_policy(struct dm_task *dmt, struct dso_state *state)
|
||||
{
|
||||
#if THIN_DEBUG
|
||||
log_info("dmeventd executes: %s.", state->cmd_str);
|
||||
@@ -306,12 +248,10 @@ static int _use_policy(struct dm_task *dmt, struct dso_state *state)
|
||||
if (!dmeventd_lvm2_run_with_lock(state->cmd_str)) {
|
||||
log_error("Failed to extend thin pool %s.",
|
||||
dm_task_get_name(dmt));
|
||||
_umount(dmt);
|
||||
state->fails++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
state->fails = 0;
|
||||
return 1;
|
||||
} else
|
||||
state->fails = 0;
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt,
|
||||
@@ -327,13 +267,6 @@ void process_event(struct dm_task *dmt,
|
||||
char *target_type = NULL;
|
||||
char *params;
|
||||
int needs_policy = 0;
|
||||
int needs_umount = 0;
|
||||
|
||||
#if THIN_DEBUG
|
||||
log_debug("Watch for tp-data:%.2f%% tp-metadata:%.2f%%.",
|
||||
dm_percent_to_float(state->data_percent_check),
|
||||
dm_percent_to_float(state->metadata_percent_check));
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* No longer monitoring, waiting for remove */
|
||||
@@ -342,10 +275,8 @@ void process_event(struct dm_task *dmt,
|
||||
#endif
|
||||
if (event & DM_EVENT_DEVICE_ERROR) {
|
||||
/* Error -> no need to check and do instant resize */
|
||||
if (_use_policy(dmt, state))
|
||||
goto out;
|
||||
|
||||
stack;
|
||||
_use_policy(dmt, state);
|
||||
goto out;
|
||||
}
|
||||
|
||||
dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms);
|
||||
@@ -357,7 +288,7 @@ void process_event(struct dm_task *dmt,
|
||||
|
||||
if (!dm_get_status_thin_pool(state->mem, params, &tps)) {
|
||||
log_error("Failed to parse status.");
|
||||
needs_umount = 1;
|
||||
_umount(dmt);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -392,9 +323,6 @@ void process_event(struct dm_task *dmt,
|
||||
log_warn("WARNING: Thin pool %s metadata is now %.2f%% full.",
|
||||
device, dm_percent_to_float(percent));
|
||||
needs_policy = 1;
|
||||
|
||||
if (percent >= UMOUNT_THRESH)
|
||||
needs_umount = 1;
|
||||
}
|
||||
|
||||
percent = dm_make_percent(tps->used_data_blocks, tps->total_data_blocks);
|
||||
@@ -409,27 +337,17 @@ void process_event(struct dm_task *dmt,
|
||||
log_warn("WARNING: Thin pool %s data is now %.2f%% full.",
|
||||
device, dm_percent_to_float(percent));
|
||||
needs_policy = 1;
|
||||
|
||||
if (percent >= UMOUNT_THRESH)
|
||||
needs_umount = 1;
|
||||
}
|
||||
|
||||
if (needs_policy &&
|
||||
_use_policy(dmt, state))
|
||||
needs_umount = 0; /* No umount when command was successful */
|
||||
if (needs_policy)
|
||||
_use_policy(dmt, state);
|
||||
out:
|
||||
if (needs_umount) {
|
||||
_umount(dmt);
|
||||
/* Until something changes, do not retry any more actions */
|
||||
state->data_percent_check = state->metadata_percent_check = (DM_PERCENT_1 * 101);
|
||||
}
|
||||
|
||||
if (tps)
|
||||
dm_pool_free(state->mem, tps);
|
||||
|
||||
if (state->fails >= MAX_FAILS) {
|
||||
log_warn("WARNING: Dropping monitoring of %s. "
|
||||
"lvm2 command fails too often (%u times in row).",
|
||||
"lvm2 command fails too often (%u times in raw).",
|
||||
device, state->fails);
|
||||
pthread_kill(pthread_self(), SIGALRM);
|
||||
}
|
||||
@@ -458,11 +376,11 @@ int register_device(const char *device,
|
||||
state->data_percent_check = CHECK_MINIMUM;
|
||||
*user = state;
|
||||
|
||||
log_info("Monitoring thin pool %s.", device);
|
||||
log_info("Monitoring thin %s.", device);
|
||||
|
||||
return 1;
|
||||
bad:
|
||||
log_error("Failed to monitor thin pool %s.", device);
|
||||
log_error("Failed to monitor thin %s.", device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -476,7 +394,7 @@ int unregister_device(const char *device,
|
||||
struct dso_state *state = *user;
|
||||
|
||||
dmeventd_lvm2_exit_with_pool(state);
|
||||
log_info("No longer monitoring thin pool %s.", device);
|
||||
log_info("No longer monitoring thin %s.", device);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@@ -57,11 +57,9 @@ install_lvmdbusd:
|
||||
$(INSTALL_DATA) $(LVMDBUS_BUILDDIR_FILES) $(DESTDIR)$(lvmdbusdir)
|
||||
PYTHON=$(PYTHON3) $(PYCOMPILE) --destdir "$(DESTDIR)" --basedir "$(lvmdbusdir)" $(LVMDBUS_SRCDIR_FILES) $(LVMDBUS_BUILDDIR_FILES)
|
||||
$(CHMOD) 755 $(DESTDIR)$(lvmdbusdir)/__pycache__
|
||||
$(CHMOD) 444 $(DESTDIR)$(lvmdbusdir)/__pycache__/*.py[co]
|
||||
$(CHMOD) 444 $(DESTDIR)$(lvmdbusdir)/__pycache__/*.pyc $(DESTDIR)$(lvmdbusdir)/__pycache__/*.pyo
|
||||
|
||||
install_lvm2: install_lvmdbusd
|
||||
|
||||
install: install_lvm2
|
||||
|
||||
DISTCLEAN_TARGETS+= \
|
||||
$(LVMDBUS_BUILDDIR_FILES)
|
||||
|
@@ -8,7 +8,6 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import dbus
|
||||
import dbus.service
|
||||
from . import cfg
|
||||
from .utils import get_properties, add_properties, get_object_property_diff, \
|
||||
log_debug
|
||||
|
@@ -13,9 +13,9 @@ from . import cfg
|
||||
import time
|
||||
from .cmdhandler import options_to_cli_args
|
||||
import dbus
|
||||
from .utils import pv_range_append, pv_dest_ranges, log_error, log_debug
|
||||
import traceback
|
||||
import os
|
||||
from .job import Job, JobState
|
||||
from .utils import pv_range_append, pv_dest_ranges
|
||||
from .request import RequestEntry
|
||||
|
||||
_rlock = threading.RLock()
|
||||
_thread_list = list()
|
||||
@@ -42,22 +42,40 @@ def lv_merge_cmd(merge_options, lv_full_name):
|
||||
return cmd
|
||||
|
||||
|
||||
def _move_merge(interface_name, cmd, job_state):
|
||||
add(cmd, job_state)
|
||||
def _create_background_dbus_job(job_state):
|
||||
job_obj = Job(None, job_state)
|
||||
cfg.om.register_object(job_obj)
|
||||
return job_obj.dbus_object_path()
|
||||
|
||||
done = job_state.Wait(-1)
|
||||
if not done:
|
||||
ec, err_msg = job_state.GetError
|
||||
raise dbus.exceptions.DBusException(
|
||||
interface_name,
|
||||
'Exit code %s, stderr = %s' % (str(ec), err_msg))
|
||||
|
||||
cfg.load()
|
||||
return '/'
|
||||
def _move_merge(interface_name, cmd, time_out, skip_first_line=False):
|
||||
# Create job object to be used while running the command
|
||||
rc = '/'
|
||||
job_state = JobState(None)
|
||||
add(cmd, job_state, skip_first_line)
|
||||
|
||||
if time_out == -1:
|
||||
# Waiting forever
|
||||
done = job_state.Wait(time_out)
|
||||
if not done:
|
||||
ec, err_msg = job_state.GetError
|
||||
raise dbus.exceptions.DBusException(
|
||||
interface_name,
|
||||
'Exit code %s, stderr = %s' % (str(ec), err_msg))
|
||||
elif time_out == 0:
|
||||
# Immediately create and return a job
|
||||
rc = _create_background_dbus_job(job_state)
|
||||
else:
|
||||
# Willing to wait for a bit
|
||||
done = job_state.Wait(time_out)
|
||||
if not done:
|
||||
rc = _create_background_dbus_job(job_state)
|
||||
|
||||
return rc
|
||||
|
||||
|
||||
def move(interface_name, lv_name, pv_src_obj, pv_source_range,
|
||||
pv_dests_and_ranges, move_options, job_state):
|
||||
pv_dests_and_ranges, move_options, time_out):
|
||||
"""
|
||||
Common code for the pvmove handling.
|
||||
:param interface_name: What dbus interface we are providing for
|
||||
@@ -66,8 +84,8 @@ def move(interface_name, lv_name, pv_src_obj, pv_source_range,
|
||||
:param pv_source_range: (0,0 to ignore, else start, end segments)
|
||||
:param pv_dests_and_ranges: Array of PV object paths and start/end segs
|
||||
:param move_options: Hash with optional arguments
|
||||
:param job_state: Used to convey information about jobs between processes
|
||||
:return: '/' When complete, the empty object path
|
||||
:param time_out:
|
||||
:return: Object path to job object
|
||||
"""
|
||||
pv_dests = []
|
||||
pv_src = cfg.om.get_object_by_path(pv_src_obj)
|
||||
@@ -93,18 +111,18 @@ def move(interface_name, lv_name, pv_src_obj, pv_source_range,
|
||||
pv_source_range,
|
||||
pv_dests)
|
||||
|
||||
return _move_merge(interface_name, cmd, job_state)
|
||||
return _move_merge(interface_name, cmd, time_out)
|
||||
else:
|
||||
raise dbus.exceptions.DBusException(
|
||||
interface_name, 'pv_src_obj (%s) not found' % pv_src_obj)
|
||||
|
||||
|
||||
def merge(interface_name, lv_uuid, lv_name, merge_options, job_state):
|
||||
def merge(interface_name, lv_uuid, lv_name, merge_options, time_out):
|
||||
# Make sure we have a dbus object representing it
|
||||
dbo = cfg.om.get_object_by_uuid_lvm_id(lv_uuid, lv_name)
|
||||
if dbo:
|
||||
cmd = lv_merge_cmd(merge_options, dbo.lvm_id)
|
||||
return _move_merge(interface_name, cmd, job_state)
|
||||
return _move_merge(interface_name, cmd, time_out, True)
|
||||
else:
|
||||
raise dbus.exceptions.DBusException(
|
||||
interface_name,
|
||||
@@ -119,96 +137,59 @@ def background_reaper():
|
||||
for i in range(num_threads, -1, -1):
|
||||
_thread_list[i].join(0)
|
||||
if not _thread_list[i].is_alive():
|
||||
log_debug("Removing thread: %s" % _thread_list[i].name)
|
||||
_thread_list.pop(i)
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
|
||||
def background_execute(command, background_job):
|
||||
|
||||
# Wrap this whole operation in an exception handler, otherwise if we
|
||||
# hit a code bug we will silently exit this thread without anyone being
|
||||
# the wiser.
|
||||
try:
|
||||
# We need to execute these command stand alone by forking & exec'ing
|
||||
# the command always!
|
||||
command.insert(0, cfg.LVM_CMD)
|
||||
process = subprocess.Popen(command, stdout=subprocess.PIPE,
|
||||
env=os.environ,
|
||||
stderr=subprocess.PIPE, close_fds=True)
|
||||
|
||||
log_debug("Background process for %s is %d" %
|
||||
(str(command), process.pid))
|
||||
|
||||
lines_iterator = iter(process.stdout.readline, b"")
|
||||
for line in lines_iterator:
|
||||
line_str = line.decode("utf-8")
|
||||
|
||||
# Check to see if the line has the correct number of separators
|
||||
try:
|
||||
if line_str.count(':') == 2:
|
||||
(device, ignore, percentage) = line_str.split(':')
|
||||
background_job.Percent = round(
|
||||
float(percentage.strip()[:-1]), 1)
|
||||
except ValueError:
|
||||
log_error("Trying to parse percentage which failed for %s" %
|
||||
line_str)
|
||||
|
||||
out = process.communicate()
|
||||
|
||||
if process.returncode == 0:
|
||||
background_job.Percent = 100
|
||||
else:
|
||||
log_error("Failed to execute background job %s, STDERR= %s"
|
||||
% (str(command), out[1]))
|
||||
|
||||
background_job.set_result(process.returncode, out[1])
|
||||
log_debug("Background process %d complete!" % process.pid)
|
||||
|
||||
except Exception:
|
||||
# In the unlikely event that we blow up, we need to unblock caller which
|
||||
# is waiting on an answer.
|
||||
st = traceback.format_exc()
|
||||
error = "Exception in background thread: \n%s" % st
|
||||
log_error(error)
|
||||
background_job.set_result(1, error)
|
||||
def process_background_result(job_object, exit_code, error_msg):
|
||||
cfg.load()
|
||||
job_object.set_result(exit_code, error_msg)
|
||||
return None
|
||||
|
||||
|
||||
def add(command, reporting_job):
|
||||
# noinspection PyUnusedLocal
|
||||
def empty_cb(disregard):
|
||||
pass
|
||||
|
||||
|
||||
def background_execute(command, background_job, skip_first_line=False):
|
||||
process = subprocess.Popen(command, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE, close_fds=True)
|
||||
lines_iterator = iter(process.stdout.readline, b"")
|
||||
for line in lines_iterator:
|
||||
# Merge ouputs a line before updates, move does not
|
||||
if skip_first_line:
|
||||
skip_first_line = False
|
||||
continue
|
||||
|
||||
if len(line) > 10:
|
||||
(device, ignore, percentage) = line.decode("utf-8").split(':')
|
||||
background_job.Percent = round(float(percentage.strip()[:-1]), 1)
|
||||
|
||||
out = process.communicate()
|
||||
|
||||
# print "DEBUG: EC %d, STDOUT %s, STDERR %s" % \
|
||||
# (process.returncode, out[0], out[1])
|
||||
|
||||
if process.returncode == 0:
|
||||
background_job.Percent = 100
|
||||
|
||||
# Queue up the result so that it gets executed in same thread as others.
|
||||
r = RequestEntry(
|
||||
-1, process_background_result,
|
||||
(background_job, process.returncode, out[1]),
|
||||
empty_cb, empty_cb, False)
|
||||
cfg.worker_q.put(r)
|
||||
|
||||
|
||||
def add(command, reporting_job, skip_first_line=False):
|
||||
# Create the thread, get it running and then add it to the list
|
||||
t = threading.Thread(
|
||||
target=background_execute,
|
||||
name="thread: " + ' '.join(command),
|
||||
args=(command, reporting_job))
|
||||
args=(command, reporting_job, skip_first_line))
|
||||
t.start()
|
||||
|
||||
with _rlock:
|
||||
_thread_list.append(t)
|
||||
|
||||
|
||||
def wait_thread(job, timeout, cb, cbe):
|
||||
# We need to put the wait on it's own thread, so that we don't block the
|
||||
# entire dbus queue processing thread
|
||||
try:
|
||||
cb(job.state.Wait(timeout))
|
||||
except Exception as e:
|
||||
cbe("Wait exception: %s" % str(e))
|
||||
return 0
|
||||
|
||||
|
||||
def add_wait(job, timeout, cb, cbe):
|
||||
|
||||
if timeout == 0:
|
||||
# Users are basically polling, do not create thread
|
||||
cb(job.Complete)
|
||||
else:
|
||||
t = threading.Thread(
|
||||
target=wait_thread,
|
||||
name="thread job.Wait: %s" % job.dbus_object_path(),
|
||||
args=(job, timeout, cb, cbe)
|
||||
)
|
||||
|
||||
t.start()
|
||||
with _rlock:
|
||||
_thread_list.append(t)
|
||||
|
@@ -11,8 +11,10 @@ import os
|
||||
import multiprocessing
|
||||
import queue
|
||||
import itertools
|
||||
|
||||
from lvmdbusd import path
|
||||
try:
|
||||
from . import path
|
||||
except SystemError:
|
||||
import path
|
||||
|
||||
LVM_CMD = os.getenv('LVM_BINARY', path.LVM_BINARY)
|
||||
|
||||
@@ -22,18 +24,14 @@ om = None
|
||||
# This is the global bus connection
|
||||
bus = None
|
||||
|
||||
# Command line args
|
||||
args = None
|
||||
|
||||
# Set to true if we are depending on external events for updates
|
||||
ee = False
|
||||
|
||||
# Shared state variable across all processes
|
||||
run = multiprocessing.Value('i', 1)
|
||||
|
||||
# If this is set to true, the current setup support lvm shell and we are
|
||||
# running in that mode of operation
|
||||
SHELL_IN_USE = None
|
||||
# Debug
|
||||
DEBUG = True
|
||||
|
||||
# Use lvm shell
|
||||
USE_SHELL = False
|
||||
|
||||
# Lock used by pprint
|
||||
stdout_lock = multiprocessing.Lock()
|
||||
@@ -80,6 +78,3 @@ load = None
|
||||
|
||||
# Global cached state
|
||||
db = None
|
||||
|
||||
# lvm flight recorder
|
||||
blackbox = None
|
||||
|
@@ -11,9 +11,6 @@ from subprocess import Popen, PIPE
|
||||
import time
|
||||
import threading
|
||||
from itertools import chain
|
||||
import collections
|
||||
import traceback
|
||||
import os
|
||||
|
||||
try:
|
||||
from . import cfg
|
||||
@@ -24,11 +21,6 @@ except SystemError:
|
||||
from utils import pv_dest_ranges, log_debug, log_error
|
||||
from lvm_shell_proxy import LVMShellProxy
|
||||
|
||||
try:
|
||||
import simplejson as json
|
||||
except ImportError:
|
||||
import json
|
||||
|
||||
SEP = '{|}'
|
||||
|
||||
total_time = 0.0
|
||||
@@ -36,45 +28,11 @@ total_count = 0
|
||||
|
||||
# We need to prevent different threads from using the same lvm shell
|
||||
# at the same time.
|
||||
cmd_lock = threading.RLock()
|
||||
cmd_lock = threading.Lock()
|
||||
|
||||
|
||||
class LvmExecutionMeta(object):
|
||||
|
||||
def __init__(self, start, ended, cmd, ec, stdout_txt, stderr_txt):
|
||||
self.start = start
|
||||
self.ended = ended
|
||||
self.cmd = cmd
|
||||
self.ec = ec
|
||||
self.stdout_txt = stdout_txt
|
||||
self.stderr_txt = stderr_txt
|
||||
|
||||
def __str__(self):
|
||||
return "EC= %d for %s\n" \
|
||||
"STARTED: %f, ENDED: %f\n" \
|
||||
"STDOUT=%s\n" \
|
||||
"STDERR=%s\n" % \
|
||||
(self.ec, str(self.cmd), self.start, self.ended, self.stdout_txt,
|
||||
self.stderr_txt)
|
||||
|
||||
|
||||
class LvmFlightRecorder(object):
|
||||
|
||||
def __init__(self):
|
||||
self.queue = collections.deque(maxlen=16)
|
||||
|
||||
def add(self, lvm_exec_meta):
|
||||
self.queue.append(lvm_exec_meta)
|
||||
|
||||
def dump(self):
|
||||
with cmd_lock:
|
||||
log_error("LVM dbus flight recorder START")
|
||||
for c in self.queue:
|
||||
log_error(str(c))
|
||||
log_error("LVM dbus flight recorder END")
|
||||
|
||||
|
||||
cfg.blackbox = LvmFlightRecorder()
|
||||
# The actual method which gets called to invoke the lvm command, can vary
|
||||
# from forking a new process to using lvm shell
|
||||
_t_call = None
|
||||
|
||||
|
||||
def _debug_c(cmd, exit_code, out):
|
||||
@@ -98,8 +56,7 @@ def call_lvm(command, debug=False):
|
||||
# in different locations on the same box
|
||||
command.insert(0, cfg.LVM_CMD)
|
||||
|
||||
process = Popen(command, stdout=PIPE, stderr=PIPE, close_fds=True,
|
||||
env=os.environ)
|
||||
process = Popen(command, stdout=PIPE, stderr=PIPE, close_fds=True)
|
||||
out = process.communicate()
|
||||
|
||||
stdout_text = bytes(out[0]).decode("utf-8")
|
||||
@@ -108,47 +65,37 @@ def call_lvm(command, debug=False):
|
||||
if debug or process.returncode != 0:
|
||||
_debug_c(command, process.returncode, (stdout_text, stderr_text))
|
||||
|
||||
return process.returncode, stdout_text, stderr_text
|
||||
if process.returncode == 0:
|
||||
if cfg.DEBUG and out[1] and len(out[1]):
|
||||
log_error('WARNING: lvm is out-putting text to STDERR on success!')
|
||||
_debug_c(command, process.returncode, (stdout_text, stderr_text))
|
||||
|
||||
# The actual method which gets called to invoke the lvm command, can vary
|
||||
# from forking a new process to using lvm shell
|
||||
_t_call = call_lvm
|
||||
return process.returncode, stdout_text, stderr_text
|
||||
|
||||
|
||||
def _shell_cfg():
|
||||
global _t_call
|
||||
try:
|
||||
lvm_shell = LVMShellProxy()
|
||||
_t_call = lvm_shell.call_lvm
|
||||
cfg.SHELL_IN_USE = lvm_shell
|
||||
return True
|
||||
except Exception:
|
||||
_t_call = call_lvm
|
||||
cfg.SHELL_IN_USE = None
|
||||
log_error(traceback.format_exc())
|
||||
log_error("Unable to utilize lvm shell, dropping back to fork & exec")
|
||||
return False
|
||||
log_debug('Using lvm shell!')
|
||||
lvm_shell = LVMShellProxy()
|
||||
_t_call = lvm_shell.call_lvm
|
||||
|
||||
|
||||
if cfg.USE_SHELL:
|
||||
_shell_cfg()
|
||||
else:
|
||||
_t_call = call_lvm
|
||||
|
||||
|
||||
def set_execution(shell):
|
||||
global _t_call
|
||||
with cmd_lock:
|
||||
# If the user requested lvm shell and we are currently setup that
|
||||
# way, just return
|
||||
if cfg.SHELL_IN_USE and shell:
|
||||
return True
|
||||
else:
|
||||
if not shell and cfg.SHELL_IN_USE:
|
||||
cfg.SHELL_IN_USE.exit_shell()
|
||||
cfg.SHELL_IN_USE = None
|
||||
|
||||
_t_call = call_lvm
|
||||
_t_call = None
|
||||
if shell:
|
||||
if cfg.args.use_json:
|
||||
return _shell_cfg()
|
||||
else:
|
||||
return False
|
||||
return True
|
||||
log_debug('Using lvm shell!')
|
||||
lvm_shell = LVMShellProxy()
|
||||
_t_call = lvm_shell.call_lvm
|
||||
else:
|
||||
_t_call = call_lvm
|
||||
|
||||
|
||||
def time_wrapper(command, debug=False):
|
||||
@@ -158,10 +105,9 @@ def time_wrapper(command, debug=False):
|
||||
with cmd_lock:
|
||||
start = time.time()
|
||||
results = _t_call(command, debug)
|
||||
ended = time.time()
|
||||
total_time += (ended - start)
|
||||
total_time += (time.time() - start)
|
||||
total_count += 1
|
||||
cfg.blackbox.add(LvmExecutionMeta(start, ended, command, *results))
|
||||
|
||||
return results
|
||||
|
||||
|
||||
@@ -228,10 +174,6 @@ def pv_remove(device, remove_options):
|
||||
return call(cmd)
|
||||
|
||||
|
||||
def _qt(tag_name):
|
||||
return '@%s' % tag_name
|
||||
|
||||
|
||||
def _tag(operation, what, add, rm, tag_options):
|
||||
cmd = [operation]
|
||||
cmd.extend(options_to_cli_args(tag_options))
|
||||
@@ -242,11 +184,9 @@ def _tag(operation, what, add, rm, tag_options):
|
||||
cmd.append(what)
|
||||
|
||||
if add:
|
||||
cmd.extend(list(chain.from_iterable(
|
||||
('--addtag', _qt(x)) for x in add)))
|
||||
cmd.extend(list(chain.from_iterable(('--addtag', x) for x in add)))
|
||||
if rm:
|
||||
cmd.extend(list(chain.from_iterable(
|
||||
('--deltag', _qt(x)) for x in rm)))
|
||||
cmd.extend(list(chain.from_iterable(('--deltag', x) for x in rm)))
|
||||
|
||||
return call(cmd, False)
|
||||
|
||||
@@ -426,7 +366,7 @@ def lv_cache_lv(cache_pool_full_name, lv_full_name, cache_options):
|
||||
# lvconvert --type cache --cachepool VG/CachePoolLV VG/OriginLV
|
||||
cmd = ['lvconvert']
|
||||
cmd.extend(options_to_cli_args(cache_options))
|
||||
cmd.extend(['-y', '--type', 'cache', '--cachepool',
|
||||
cmd.extend(['--type', 'cache', '--cachepool',
|
||||
cache_pool_full_name, lv_full_name])
|
||||
return call(cmd)
|
||||
|
||||
@@ -446,84 +386,19 @@ def lv_detach_cache(lv_full_name, detach_options, destroy_cache):
|
||||
return call(cmd)
|
||||
|
||||
|
||||
def supports_json():
|
||||
cmd = ['help']
|
||||
rc, out, err = call(cmd)
|
||||
if rc == 0:
|
||||
if cfg.SHELL_IN_USE:
|
||||
return True
|
||||
else:
|
||||
if 'fullreport' in err:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def lvm_full_report_json():
|
||||
pv_columns = ['pv_name', 'pv_uuid', 'pv_fmt', 'pv_size', 'pv_free',
|
||||
'pv_used', 'dev_size', 'pv_mda_size', 'pv_mda_free',
|
||||
'pv_ba_start', 'pv_ba_size', 'pe_start', 'pv_pe_count',
|
||||
'pv_pe_alloc_count', 'pv_attr', 'pv_tags', 'vg_name',
|
||||
'vg_uuid', 'pv_missing']
|
||||
|
||||
pv_seg_columns = ['pvseg_start', 'pvseg_size', 'segtype',
|
||||
'pv_uuid', 'lv_uuid', 'pv_name']
|
||||
|
||||
vg_columns = ['vg_name', 'vg_uuid', 'vg_fmt', 'vg_size', 'vg_free',
|
||||
'vg_sysid', 'vg_extent_size', 'vg_extent_count',
|
||||
'vg_free_count', 'vg_profile', 'max_lv', 'max_pv',
|
||||
'pv_count', 'lv_count', 'snap_count', 'vg_seqno',
|
||||
'vg_mda_count', 'vg_mda_free', 'vg_mda_size',
|
||||
'vg_mda_used_count', 'vg_attr', 'vg_tags']
|
||||
|
||||
lv_columns = ['lv_uuid', 'lv_name', 'lv_path', 'lv_size',
|
||||
'vg_name', 'pool_lv_uuid', 'pool_lv', 'origin_uuid',
|
||||
'origin', 'data_percent',
|
||||
'lv_attr', 'lv_tags', 'vg_uuid', 'lv_active', 'data_lv',
|
||||
'metadata_lv', 'lv_parent', 'lv_role', 'lv_layout',
|
||||
'snap_percent', 'metadata_percent', 'copy_percent',
|
||||
'sync_percent', 'lv_metadata_size', 'move_pv', 'move_pv_uuid']
|
||||
|
||||
lv_seg_columns = ['seg_pe_ranges', 'segtype', 'lv_uuid']
|
||||
|
||||
cmd = _dc('fullreport', [
|
||||
'-a', # Need hidden too
|
||||
'--configreport', 'pv', '-o', ','.join(pv_columns),
|
||||
'--configreport', 'vg', '-o', ','.join(vg_columns),
|
||||
'--configreport', 'lv', '-o', ','.join(lv_columns),
|
||||
'--configreport', 'seg', '-o', ','.join(lv_seg_columns),
|
||||
'--configreport', 'pvseg', '-o', ','.join(pv_seg_columns),
|
||||
'--reportformat', 'json'
|
||||
])
|
||||
|
||||
rc, out, err = call(cmd)
|
||||
if rc == 0:
|
||||
# With the current implementation, if we are using the shell then we
|
||||
# are using JSON and JSON is returned back to us as it was parsed to
|
||||
# figure out if we completed OK or not
|
||||
if cfg.SHELL_IN_USE:
|
||||
assert(type(out) == dict)
|
||||
return out
|
||||
else:
|
||||
return json.loads(out)
|
||||
return None
|
||||
|
||||
|
||||
def pv_retrieve_with_segs(device=None):
|
||||
d = []
|
||||
err = ""
|
||||
out = ""
|
||||
rc = 0
|
||||
|
||||
columns = ['pv_name', 'pv_uuid', 'pv_fmt', 'pv_size', 'pv_free',
|
||||
'pv_used', 'dev_size', 'pv_mda_size', 'pv_mda_free',
|
||||
'pv_ba_start', 'pv_ba_size', 'pe_start', 'pv_pe_count',
|
||||
'pv_pe_alloc_count', 'pv_attr', 'pv_tags', 'vg_name',
|
||||
'vg_uuid', 'pvseg_start', 'pvseg_size', 'segtype', 'pv_missing']
|
||||
'vg_uuid', 'pv_seg_start', 'pvseg_size', 'segtype']
|
||||
|
||||
# Lvm has some issues where it returns failure when querying pvs when other
|
||||
# operations are in process, see:
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=1274085
|
||||
for i in range(0, 10):
|
||||
while True:
|
||||
cmd = _dc('pvs', ['-o', ','.join(columns)])
|
||||
|
||||
if device:
|
||||
@@ -538,13 +413,6 @@ def pv_retrieve_with_segs(device=None):
|
||||
time.sleep(0.2)
|
||||
log_debug("LVM Bug workaround, retrying pvs command...")
|
||||
|
||||
if rc != 0:
|
||||
msg = "We were unable to get pvs to return without error after " \
|
||||
"trying 10 times, RC=%d, STDERR=(%s), STDOUT=(%s)" % \
|
||||
(rc, err, out)
|
||||
log_error(msg)
|
||||
raise RuntimeError(msg)
|
||||
|
||||
return d
|
||||
|
||||
|
||||
@@ -731,9 +599,7 @@ def lv_retrieve_with_segments():
|
||||
'origin', 'data_percent',
|
||||
'lv_attr', 'lv_tags', 'vg_uuid', 'lv_active', 'data_lv',
|
||||
'metadata_lv', 'seg_pe_ranges', 'segtype', 'lv_parent',
|
||||
'lv_role', 'lv_layout',
|
||||
'snap_percent', 'metadata_percent', 'copy_percent',
|
||||
'sync_percent', 'lv_metadata_size', 'move_pv', 'move_pv_uuid']
|
||||
'lv_role', 'lv_layout']
|
||||
|
||||
cmd = _dc('lvs', ['-a', '-o', ','.join(columns)])
|
||||
rc, out, err = call(cmd)
|
||||
|
@@ -13,12 +13,11 @@ from . import cfg
|
||||
from .cfg import JOB_INTERFACE
|
||||
import dbus
|
||||
import threading
|
||||
from . import background
|
||||
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
class JobState(object):
|
||||
def __init__(self, request=None):
|
||||
def __init__(self, request):
|
||||
self.rlock = threading.RLock()
|
||||
|
||||
self._percent = 0
|
||||
@@ -49,6 +48,8 @@ class JobState(object):
|
||||
with self.rlock:
|
||||
if self._request:
|
||||
self._complete = self._request.is_done()
|
||||
if self._complete:
|
||||
self._percent = 100
|
||||
|
||||
return self._complete
|
||||
|
||||
@@ -56,7 +57,6 @@ class JobState(object):
|
||||
def Complete(self, value):
|
||||
with self.rlock:
|
||||
self._complete = value
|
||||
self._percent = 100
|
||||
self._cond.notify_all()
|
||||
|
||||
@property
|
||||
@@ -104,7 +104,7 @@ class JobState(object):
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
class Job(AutomatedProperties):
|
||||
_Percent_meta = ('d', JOB_INTERFACE)
|
||||
_Percent_meta = ('y', JOB_INTERFACE)
|
||||
_Complete_meta = ('b', JOB_INTERFACE)
|
||||
_Result_meta = ('o', JOB_INTERFACE)
|
||||
_GetError_meta = ('(is)', JOB_INTERFACE)
|
||||
@@ -120,7 +120,7 @@ class Job(AutomatedProperties):
|
||||
|
||||
@property
|
||||
def Percent(self):
|
||||
return dbus.Double(float(self.state.Percent))
|
||||
return self.state.Percent
|
||||
|
||||
@Percent.setter
|
||||
def Percent(self, value):
|
||||
@@ -128,7 +128,7 @@ class Job(AutomatedProperties):
|
||||
|
||||
@property
|
||||
def Complete(self):
|
||||
return dbus.Boolean(self.state.Complete)
|
||||
return self.state.Complete
|
||||
|
||||
@Complete.setter
|
||||
def Complete(self, value):
|
||||
@@ -136,7 +136,7 @@ class Job(AutomatedProperties):
|
||||
|
||||
@property
|
||||
def GetError(self):
|
||||
return dbus.Struct(self.state.GetError, signature="(is)")
|
||||
return self.state.GetError
|
||||
|
||||
def set_result(self, ec, msg):
|
||||
self.state.set_result(ec, msg)
|
||||
@@ -152,14 +152,13 @@ class Job(AutomatedProperties):
|
||||
|
||||
@dbus.service.method(dbus_interface=JOB_INTERFACE,
|
||||
in_signature='i',
|
||||
out_signature='b',
|
||||
async_callbacks=('cb', 'cbe'))
|
||||
def Wait(self, timeout, cb, cbe):
|
||||
background.add_wait(self, timeout, cb, cbe)
|
||||
out_signature='b')
|
||||
def Wait(self, timeout):
|
||||
return self.state.Wait(timeout)
|
||||
|
||||
@property
|
||||
def Result(self):
|
||||
return dbus.ObjectPath(self.state.Result)
|
||||
return self.state.Result
|
||||
|
||||
@property
|
||||
def lvm_id(self):
|
||||
|
@@ -22,40 +22,6 @@ from .loader import common
|
||||
from .state import State
|
||||
from . import background
|
||||
from .utils import round_size
|
||||
from .job import JobState
|
||||
|
||||
|
||||
# Try and build a key for a LV, so that we sort the LVs with least dependencies
|
||||
# first. This may be error prone because of the flexibility LVM
|
||||
# provides and what you can stack.
|
||||
def get_key(i):
|
||||
|
||||
name = i['lv_name']
|
||||
parent = i['lv_parent']
|
||||
pool = i['pool_lv']
|
||||
a1 = ""
|
||||
a2 = ""
|
||||
|
||||
if name[0] == '[':
|
||||
a1 = '#'
|
||||
|
||||
# We have a parent
|
||||
if parent:
|
||||
# Check if parent is hidden
|
||||
if parent[0] == '[':
|
||||
a2 = '##'
|
||||
else:
|
||||
a2 = '#'
|
||||
|
||||
# If a LV has a pool, then it should be sorted/loaded after the pool
|
||||
# lv, unless it's a hidden too, then after other hidden, but before visible
|
||||
if pool:
|
||||
if pool[0] != '[':
|
||||
a2 += '~'
|
||||
else:
|
||||
a1 = '$' + a1
|
||||
|
||||
return "%s%s%s" % (a1, a2, name)
|
||||
|
||||
|
||||
# noinspection PyUnusedLocal
|
||||
@@ -65,13 +31,7 @@ def lvs_state_retrieve(selection, cache_refresh=True):
|
||||
if cache_refresh:
|
||||
cfg.db.refresh()
|
||||
|
||||
# When building up the model, it's best to process LVs with the least
|
||||
# dependencies to those that are dependant upon other LVs. Otherwise, when
|
||||
# we are trying to gather information we could be in a position where we
|
||||
# don't have information available yet.
|
||||
lvs = sorted(cfg.db.fetch_lvs(selection), key=get_key)
|
||||
|
||||
for l in lvs:
|
||||
for l in cfg.db.fetch_lvs(selection):
|
||||
rc.append(LvState(
|
||||
l['lv_uuid'], l['lv_name'],
|
||||
l['lv_path'], n(l['lv_size']),
|
||||
@@ -81,14 +41,7 @@ def lvs_state_retrieve(selection, cache_refresh=True):
|
||||
n32(l['data_percent']), l['lv_attr'],
|
||||
l['lv_tags'], l['lv_active'], l['data_lv'],
|
||||
l['metadata_lv'], l['segtype'], l['lv_role'],
|
||||
l['lv_layout'],
|
||||
n32(l['snap_percent']),
|
||||
n32(l['metadata_percent']),
|
||||
n32(l['copy_percent']),
|
||||
n32(l['sync_percent']),
|
||||
n(l['lv_metadata_size']),
|
||||
l['move_pv'],
|
||||
l['move_pv_uuid']))
|
||||
l['lv_layout']))
|
||||
return rc
|
||||
|
||||
|
||||
@@ -108,15 +61,9 @@ class LvState(State):
|
||||
rc = []
|
||||
for pv in sorted(cfg.db.lv_contained_pv(uuid)):
|
||||
(pv_uuid, pv_name, pv_segs) = pv
|
||||
pv_obj = cfg.om.get_object_path_by_uuid_lvm_id(pv_uuid, pv_name)
|
||||
|
||||
segs_decorate = []
|
||||
for i in pv_segs:
|
||||
segs_decorate.append((dbus.UInt64(i[0]),
|
||||
dbus.UInt64(i[1]),
|
||||
dbus.String(i[2])))
|
||||
|
||||
rc.append((dbus.ObjectPath(pv_obj), segs_decorate))
|
||||
pv_obj = cfg.om.get_object_path_by_lvm_id(
|
||||
pv_uuid, pv_name, gen_new=False)
|
||||
rc.append((pv_obj, pv_segs))
|
||||
|
||||
return dbus.Array(rc, signature="(oa(tts))")
|
||||
|
||||
@@ -137,28 +84,27 @@ class LvState(State):
|
||||
|
||||
for l in cfg.db.hidden_lvs(self.Uuid):
|
||||
full_name = "%s/%s" % (vg_name, l[1])
|
||||
op = cfg.om.get_object_path_by_uuid_lvm_id(l[0], full_name)
|
||||
op = cfg.om.get_object_path_by_lvm_id(
|
||||
l[0], full_name, gen_new=False)
|
||||
assert op
|
||||
rc.append(dbus.ObjectPath(op))
|
||||
rc.append(op)
|
||||
return rc
|
||||
|
||||
def __init__(self, Uuid, Name, Path, SizeBytes,
|
||||
vg_name, vg_uuid, pool_lv_uuid, PoolLv,
|
||||
origin_uuid, OriginLv, DataPercent, Attr, Tags, active,
|
||||
data_lv, metadata_lv, segtypes, role, layout, SnapPercent,
|
||||
MetaDataPercent, CopyPercent, SyncPercent, MetaDataSizeBytes,
|
||||
move_pv, move_pv_uuid):
|
||||
data_lv, metadata_lv, segtypes, role, layout):
|
||||
utils.init_class_from_arguments(self)
|
||||
|
||||
# The segtypes is possibly an array with potentially dupes or a single
|
||||
# value
|
||||
self._segs = dbus.Array([], signature='s')
|
||||
if not isinstance(segtypes, list):
|
||||
self._segs.append(dbus.String(segtypes))
|
||||
self._segs.append(segtypes)
|
||||
else:
|
||||
self._segs.extend([dbus.String(x) for x in set(segtypes)])
|
||||
self._segs.extend(set(segtypes))
|
||||
|
||||
self.Vg = cfg.om.get_object_path_by_uuid_lvm_id(
|
||||
self.Vg = cfg.om.get_object_path_by_lvm_id(
|
||||
vg_uuid, vg_name, vg_obj_path_generate)
|
||||
|
||||
self.Devices = LvState._pv_devices(self.Uuid)
|
||||
@@ -166,14 +112,15 @@ class LvState(State):
|
||||
if PoolLv:
|
||||
gen = utils.lv_object_path_method(Name, (Attr, layout, role))
|
||||
|
||||
self.PoolLv = cfg.om.get_object_path_by_uuid_lvm_id(
|
||||
pool_lv_uuid, '%s/%s' % (vg_name, PoolLv), gen)
|
||||
self.PoolLv = cfg.om.get_object_path_by_lvm_id(
|
||||
pool_lv_uuid, '%s/%s' % (vg_name, PoolLv),
|
||||
gen)
|
||||
else:
|
||||
self.PoolLv = '/'
|
||||
|
||||
if OriginLv:
|
||||
self.OriginLv = \
|
||||
cfg.om.get_object_path_by_uuid_lvm_id(
|
||||
cfg.om.get_object_path_by_lvm_id(
|
||||
origin_uuid, '%s/%s' % (vg_name, OriginLv),
|
||||
vg_obj_path_generate)
|
||||
else:
|
||||
@@ -190,6 +137,8 @@ class LvState(State):
|
||||
self.Name, (self.Attr, self.layout, self.role))
|
||||
|
||||
def _object_type_create(self):
|
||||
if self.Name[0] == '[':
|
||||
return LvCommon
|
||||
if self.Attr[0] == 't':
|
||||
return LvThinPool
|
||||
elif self.Attr[0] == 'C':
|
||||
@@ -197,8 +146,6 @@ class LvState(State):
|
||||
return LvCachePool
|
||||
else:
|
||||
return LvCacheLv
|
||||
elif self.Name[0] == '[':
|
||||
return LvCommon
|
||||
elif self.OriginLv != '/':
|
||||
return LvSnapShot
|
||||
else:
|
||||
@@ -206,7 +153,7 @@ class LvState(State):
|
||||
|
||||
def create_dbus_object(self, path):
|
||||
if not path:
|
||||
path = cfg.om.get_object_path_by_uuid_lvm_id(
|
||||
path = cfg.om.get_object_path_by_lvm_id(
|
||||
self.Uuid, self.lvm_id, self._object_path_create())
|
||||
|
||||
obj_ctor = self._object_type_create()
|
||||
@@ -223,23 +170,15 @@ class LvState(State):
|
||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'Name', 's')
|
||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'Path', 's')
|
||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'SizeBytes', 't')
|
||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'DataPercent', 'u')
|
||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'SegType', 'as')
|
||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'Vg', 'o')
|
||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'OriginLv', 'o')
|
||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'PoolLv', 'o')
|
||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'Devices', "a(oa(tts))")
|
||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'HiddenLvs', "ao")
|
||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'Attr', 's')
|
||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'DataPercent', 'u')
|
||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'SnapPercent', 'u')
|
||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'DataPercent', 'u')
|
||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'MetaDataPercent', 'u')
|
||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'CopyPercent', 'u')
|
||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'SyncPercent', 'u')
|
||||
@utils.dbus_property(LV_COMMON_INTERFACE, 'MetaDataSizeBytes', 't')
|
||||
class LvCommon(AutomatedProperties):
|
||||
_Tags_meta = ("as", LV_COMMON_INTERFACE)
|
||||
_Roles_meta = ("as", LV_COMMON_INTERFACE)
|
||||
_IsThinVolume_meta = ("b", LV_COMMON_INTERFACE)
|
||||
_IsThinPool_meta = ("b", LV_COMMON_INTERFACE)
|
||||
_Active_meta = ("b", LV_COMMON_INTERFACE)
|
||||
@@ -252,25 +191,12 @@ class LvCommon(AutomatedProperties):
|
||||
_FixedMinor_meta = ('b', LV_COMMON_INTERFACE)
|
||||
_ZeroBlocks_meta = ('b', LV_COMMON_INTERFACE)
|
||||
_SkipActivation_meta = ('b', LV_COMMON_INTERFACE)
|
||||
_MovePv_meta = ('o', LV_COMMON_INTERFACE)
|
||||
|
||||
def _get_move_pv(self):
|
||||
path = None
|
||||
|
||||
# It's likely that the move_pv is empty
|
||||
if self.state.move_pv_uuid and self.state.move_pv:
|
||||
path = cfg.om.get_object_path_by_uuid_lvm_id(
|
||||
self.state.move_pv_uuid, self.state.move_pv)
|
||||
if not path:
|
||||
path = '/'
|
||||
return path
|
||||
|
||||
# noinspection PyUnusedLocal,PyPep8Naming
|
||||
def __init__(self, object_path, object_state):
|
||||
super(LvCommon, self).__init__(object_path, lvs_state_retrieve)
|
||||
self.set_interface(LV_COMMON_INTERFACE)
|
||||
self.state = object_state
|
||||
self._move_pv = self._get_move_pv()
|
||||
|
||||
@property
|
||||
def VolumeType(self):
|
||||
@@ -285,16 +211,14 @@ class LvCommon(AutomatedProperties):
|
||||
'V': 'thin Volume', 't': 'thin pool', 'T': 'Thin pool data',
|
||||
'e': 'raid or pool metadata or pool metadata spare',
|
||||
'-': 'Unspecified'}
|
||||
return dbus.Struct((self.state.Attr[0], type_map[self.state.Attr[0]]),
|
||||
signature="as")
|
||||
return (self.state.Attr[0], type_map[self.state.Attr[0]])
|
||||
|
||||
@property
|
||||
def Permissions(self):
|
||||
type_map = {'w': 'writable', 'r': 'read-only',
|
||||
'R': 'Read-only activation of non-read-only volume',
|
||||
'-': 'Unspecified'}
|
||||
return dbus.Struct((self.state.Attr[1], type_map[self.state.Attr[1]]),
|
||||
signature="(ss)")
|
||||
return (self.state.Attr[1], type_map[self.state.Attr[1]])
|
||||
|
||||
@property
|
||||
def AllocationPolicy(self):
|
||||
@@ -303,12 +227,11 @@ class LvCommon(AutomatedProperties):
|
||||
'i': 'inherited', 'I': 'inherited locked',
|
||||
'l': 'cling', 'L': 'cling locked',
|
||||
'n': 'normal', 'N': 'normal locked', '-': 'Unspecified'}
|
||||
return dbus.Struct((self.state.Attr[2], type_map[self.state.Attr[2]]),
|
||||
signature="(ss)")
|
||||
return (self.state.Attr[2], type_map[self.state.Attr[2]])
|
||||
|
||||
@property
|
||||
def FixedMinor(self):
|
||||
return dbus.Boolean(self.state.Attr[3] == 'm')
|
||||
return self.state.Attr[3] == 'm'
|
||||
|
||||
@property
|
||||
def State(self):
|
||||
@@ -319,32 +242,29 @@ class LvCommon(AutomatedProperties):
|
||||
'd': 'mapped device present without tables',
|
||||
'i': 'mapped device present with inactive table',
|
||||
'X': 'unknown', '-': 'Unspecified'}
|
||||
return dbus.Struct((self.state.Attr[4], type_map[self.state.Attr[4]]),
|
||||
signature="(ss)")
|
||||
return (self.state.Attr[4], type_map[self.state.Attr[4]])
|
||||
|
||||
@property
|
||||
def TargetType(self):
|
||||
type_map = {'C': 'Cache', 'm': 'mirror', 'r': 'raid',
|
||||
's': 'snapshot', 't': 'thin', 'u': 'unknown',
|
||||
'v': 'virtual', '-': 'Unspecified'}
|
||||
return dbus.Struct((self.state.Attr[6], type_map[self.state.Attr[6]]),
|
||||
signature="(ss)")
|
||||
return (self.state.Attr[6], type_map[self.state.Attr[6]])
|
||||
|
||||
@property
|
||||
def ZeroBlocks(self):
|
||||
return dbus.Boolean(self.state.Attr[7] == 'z')
|
||||
return self.state.Attr[7] == 'z'
|
||||
|
||||
@property
|
||||
def Health(self):
|
||||
type_map = {'p': 'partial', 'r': 'refresh',
|
||||
'm': 'mismatches', 'w': 'writemostly',
|
||||
'X': 'X unknown', '-': 'Unspecified'}
|
||||
return dbus.Struct((self.state.Attr[8], type_map[self.state.Attr[8]]),
|
||||
signature="(ss)")
|
||||
return (self.state.Attr[8], type_map[self.state.Attr[8]])
|
||||
|
||||
@property
|
||||
def SkipActivation(self):
|
||||
return dbus.Boolean(self.state.Attr[9] == 'k')
|
||||
return self.state.Attr[9] == 'k'
|
||||
|
||||
def vg_name_lookup(self):
|
||||
return self.state.vg_name_lookup()
|
||||
@@ -360,45 +280,32 @@ class LvCommon(AutomatedProperties):
|
||||
def Tags(self):
|
||||
return utils.parse_tags(self.state.Tags)
|
||||
|
||||
@property
|
||||
def Roles(self):
|
||||
return utils.parse_tags(self.state.role)
|
||||
|
||||
@property
|
||||
def lvm_id(self):
|
||||
return self.state.lvm_id
|
||||
|
||||
@property
|
||||
def IsThinVolume(self):
|
||||
return dbus.Boolean(self.state.Attr[0] == 'V')
|
||||
return self.state.Attr[0] == 'V'
|
||||
|
||||
@property
|
||||
def IsThinPool(self):
|
||||
return dbus.Boolean(self.state.Attr[0] == 't')
|
||||
return self.state.Attr[0] == 't'
|
||||
|
||||
@property
|
||||
def Active(self):
|
||||
return dbus.Boolean(self.state.active == "active")
|
||||
return self.state.active == "active"
|
||||
|
||||
@property
|
||||
def MovePv(self):
|
||||
return dbus.ObjectPath(self._move_pv)
|
||||
@dbus.service.method(
|
||||
dbus_interface=LV_COMMON_INTERFACE,
|
||||
in_signature='ia{sv}',
|
||||
out_signature='o')
|
||||
def _Future(self, tmo, open_options):
|
||||
raise dbus.exceptions.DBusException(LV_COMMON_INTERFACE, 'Do not use!')
|
||||
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
class Lv(LvCommon):
|
||||
def _fetch_hidden(self, name):
|
||||
|
||||
# The name is vg/name
|
||||
full_name = "%s/%s" % (self.vg_name_lookup(), name)
|
||||
return cfg.om.get_object_path_by_lvm_id(full_name)
|
||||
|
||||
def _get_data_meta(self):
|
||||
|
||||
# Get the data
|
||||
return (self._fetch_hidden(self.state.data_lv),
|
||||
self._fetch_hidden(self.state.metadata_lv))
|
||||
|
||||
# noinspection PyUnusedLocal,PyPep8Naming
|
||||
def __init__(self, object_path, object_state):
|
||||
super(Lv, self).__init__(object_path, object_state)
|
||||
@@ -481,21 +388,14 @@ class Lv(LvCommon):
|
||||
@dbus.service.method(
|
||||
dbus_interface=LV_INTERFACE,
|
||||
in_signature='o(tt)a(ott)ia{sv}',
|
||||
out_signature='o',
|
||||
async_callbacks=('cb', 'cbe'))
|
||||
out_signature='o')
|
||||
def Move(self, pv_src_obj, pv_source_range,
|
||||
pv_dests_and_ranges,
|
||||
tmo, move_options, cb, cbe):
|
||||
|
||||
job_state = JobState()
|
||||
|
||||
r = RequestEntry(
|
||||
tmo, background.move,
|
||||
(LV_INTERFACE, self.lvm_id, pv_src_obj, pv_source_range,
|
||||
pv_dests_and_ranges, move_options, job_state), cb, cbe, False,
|
||||
job_state)
|
||||
|
||||
cfg.worker_q.put(r)
|
||||
tmo, move_options):
|
||||
return background.move(
|
||||
LV_INTERFACE, self.lvm_id, pv_src_obj,
|
||||
pv_source_range, pv_dests_and_ranges,
|
||||
move_options, tmo)
|
||||
|
||||
@staticmethod
|
||||
def _snap_shot(lv_uuid, lv_name, name, optional_size,
|
||||
@@ -508,6 +408,8 @@ class Lv(LvCommon):
|
||||
# it is a thin lv
|
||||
if not dbo.IsThinVolume:
|
||||
if optional_size == 0:
|
||||
# TODO: Should we pick a sane default or force user to
|
||||
# make a decision?
|
||||
space = dbo.SizeBytes / 80
|
||||
remainder = space % 512
|
||||
optional_size = space + 512 - remainder
|
||||
@@ -727,6 +629,23 @@ class LvThinPool(Lv):
|
||||
_DataLv_meta = ("o", THIN_POOL_INTERFACE)
|
||||
_MetaDataLv_meta = ("o", THIN_POOL_INTERFACE)
|
||||
|
||||
def _fetch_hidden(self, name):
|
||||
|
||||
# The name is vg/name
|
||||
full_name = "%s/%s" % (self.vg_name_lookup(), name)
|
||||
|
||||
o = cfg.om.get_object_by_lvm_id(full_name)
|
||||
if o:
|
||||
return o.dbus_object_path()
|
||||
|
||||
return '/'
|
||||
|
||||
def _get_data_meta(self):
|
||||
|
||||
# Get the data
|
||||
return (self._fetch_hidden(self.state.data_lv),
|
||||
self._fetch_hidden(self.state.metadata_lv))
|
||||
|
||||
def __init__(self, object_path, object_state):
|
||||
super(LvThinPool, self).__init__(object_path, object_state)
|
||||
self.set_interface(THIN_POOL_INTERFACE)
|
||||
@@ -734,11 +653,11 @@ class LvThinPool(Lv):
|
||||
|
||||
@property
|
||||
def DataLv(self):
|
||||
return dbus.ObjectPath(self._data_lv)
|
||||
return self._data_lv
|
||||
|
||||
@property
|
||||
def MetaDataLv(self):
|
||||
return dbus.ObjectPath(self._metadata_lv)
|
||||
return self._metadata_lv
|
||||
|
||||
@staticmethod
|
||||
def _lv_create(lv_uuid, lv_name, name, size_bytes, create_options):
|
||||
@@ -783,21 +702,9 @@ class LvThinPool(Lv):
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
class LvCachePool(Lv):
|
||||
_DataLv_meta = ("o", CACHE_POOL_INTERFACE)
|
||||
_MetaDataLv_meta = ("o", CACHE_POOL_INTERFACE)
|
||||
|
||||
def __init__(self, object_path, object_state):
|
||||
super(LvCachePool, self).__init__(object_path, object_state)
|
||||
self.set_interface(CACHE_POOL_INTERFACE)
|
||||
self._data_lv, self._metadata_lv = self._get_data_meta()
|
||||
|
||||
@property
|
||||
def DataLv(self):
|
||||
return dbus.ObjectPath(self._data_lv)
|
||||
|
||||
@property
|
||||
def MetaDataLv(self):
|
||||
return dbus.ObjectPath(self._metadata_lv)
|
||||
|
||||
@staticmethod
|
||||
def _cache_lv(lv_uuid, lv_name, lv_object_path, cache_options):
|
||||
@@ -820,7 +727,8 @@ class LvCachePool(Lv):
|
||||
cfg.om.remove_object(lv_to_cache, emit_signal=True)
|
||||
cfg.load()
|
||||
|
||||
lv_converted = cfg.om.get_object_path_by_lvm_id(fcn)
|
||||
lv_converted = \
|
||||
cfg.om.get_object_by_lvm_id(fcn).dbus_object_path()
|
||||
|
||||
else:
|
||||
raise dbus.exceptions.DBusException(
|
||||
@@ -862,7 +770,7 @@ class LvCacheLv(Lv):
|
||||
|
||||
@property
|
||||
def CachePool(self):
|
||||
return dbus.ObjectPath(self.state.PoolLv)
|
||||
return self.state.PoolLv
|
||||
|
||||
@staticmethod
|
||||
def _detach_lv(lv_uuid, lv_name, detach_options, destroy_cache):
|
||||
@@ -883,7 +791,9 @@ class LvCacheLv(Lv):
|
||||
cfg.om.remove_object(dbo, emit_signal=True)
|
||||
cfg.load()
|
||||
|
||||
uncached_lv_path = cfg.om.get_object_path_by_lvm_id(lv_name)
|
||||
uncached_lv_path = \
|
||||
cfg.om.get_object_by_lvm_id(lv_name).dbus_object_path()
|
||||
|
||||
else:
|
||||
raise dbus.exceptions.DBusException(
|
||||
LV_INTERFACE,
|
||||
@@ -917,13 +827,7 @@ class LvSnapShot(Lv):
|
||||
@dbus.service.method(
|
||||
dbus_interface=SNAPSHOT_INTERFACE,
|
||||
in_signature='ia{sv}',
|
||||
out_signature='o',
|
||||
async_callbacks=('cb', 'cbe'))
|
||||
def Merge(self, tmo, merge_options, cb, cbe):
|
||||
job_state = JobState()
|
||||
|
||||
r = RequestEntry(tmo, background.merge,
|
||||
(SNAPSHOT_INTERFACE, self.Uuid, self.lvm_id,
|
||||
merge_options, job_state), cb, cbe, False,
|
||||
job_state)
|
||||
cfg.worker_q.put(r)
|
||||
out_signature='o')
|
||||
def Merge(self, tmo, merge_options):
|
||||
return background.merge(SNAPSHOT_INTERFACE, self.Uuid, self.lvm_id,
|
||||
merge_options, tmo)
|
||||
|
@@ -14,22 +14,17 @@
|
||||
import subprocess
|
||||
import shlex
|
||||
from fcntl import fcntl, F_GETFL, F_SETFL
|
||||
import os
|
||||
from os import O_NONBLOCK
|
||||
import traceback
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
import select
|
||||
import copy
|
||||
import re
|
||||
|
||||
try:
|
||||
import simplejson as json
|
||||
except ImportError:
|
||||
import json
|
||||
|
||||
|
||||
from lvmdbusd.cfg import LVM_CMD
|
||||
from lvmdbusd.utils import log_debug, log_error
|
||||
from .cfg import LVM_CMD
|
||||
from .utils import log_debug, log_error
|
||||
except:
|
||||
from cfg import LVM_CMD
|
||||
from utils import log_debug, log_error
|
||||
|
||||
SHELL_PROMPT = "lvm> "
|
||||
|
||||
@@ -43,58 +38,42 @@ def _quote_arg(arg):
|
||||
|
||||
class LVMShellProxy(object):
|
||||
def _read_until_prompt(self):
|
||||
prev_ec = None
|
||||
stdout = ""
|
||||
report = ""
|
||||
stderr = ""
|
||||
|
||||
# Try reading from all FDs to prevent one from filling up and causing
|
||||
# a hang. We are also assuming that we won't get the lvm prompt back
|
||||
# until we have already received all the output from stderr and the
|
||||
# report descriptor too.
|
||||
while not stdout.endswith(SHELL_PROMPT):
|
||||
try:
|
||||
rd_fd = [
|
||||
self.lvm_shell.stdout.fileno(),
|
||||
self.report_r,
|
||||
self.lvm_shell.stderr.fileno()]
|
||||
ready = select.select(rd_fd, [], [], 2)
|
||||
|
||||
for r in ready[0]:
|
||||
if r == self.lvm_shell.stdout.fileno():
|
||||
while True:
|
||||
tmp = self.lvm_shell.stdout.read()
|
||||
if tmp:
|
||||
stdout += tmp.decode("utf-8")
|
||||
else:
|
||||
break
|
||||
|
||||
elif r == self.report_r:
|
||||
while True:
|
||||
tmp = os.read(self.report_r, 16384)
|
||||
if tmp:
|
||||
report += tmp.decode("utf-8")
|
||||
if len(tmp) != 16384:
|
||||
break
|
||||
else:
|
||||
break
|
||||
|
||||
elif r == self.lvm_shell.stderr.fileno():
|
||||
while True:
|
||||
tmp = self.lvm_shell.stderr.read()
|
||||
if tmp:
|
||||
stderr += tmp.decode("utf-8")
|
||||
else:
|
||||
break
|
||||
|
||||
# Check to see if the lvm process died on us
|
||||
if self.lvm_shell.poll():
|
||||
raise Exception(self.lvm_shell.returncode, "%s" % stderr)
|
||||
|
||||
except IOError as ioe:
|
||||
log_debug(str(ioe))
|
||||
tmp = self.lvm_shell.stdout.read()
|
||||
if tmp:
|
||||
stdout += tmp.decode("utf-8")
|
||||
except IOError:
|
||||
# nothing written yet
|
||||
pass
|
||||
|
||||
return stdout, report, stderr
|
||||
# strip the prompt from the STDOUT before returning and grab the exit
|
||||
# code if it's available
|
||||
m = self.re.match(stdout)
|
||||
if m:
|
||||
prev_ec = int(m.group(2))
|
||||
strip_idx = -1 * len(m.group(1))
|
||||
else:
|
||||
strip_idx = -1 * len(SHELL_PROMPT)
|
||||
|
||||
return stdout[:strip_idx], prev_ec
|
||||
|
||||
def _read_line(self):
|
||||
while True:
|
||||
try:
|
||||
tmp = self.lvm_shell.stdout.readline()
|
||||
if tmp:
|
||||
return tmp.decode("utf-8")
|
||||
except IOError:
|
||||
pass
|
||||
|
||||
def _discard_echo(self, expected):
|
||||
line = ""
|
||||
while line != expected:
|
||||
# GNU readline inserts some interesting characters at times...
|
||||
line += self._read_line().replace(' \r', '')
|
||||
|
||||
def _write_cmd(self, cmd):
|
||||
cmd_bytes = bytes(cmd, "utf-8")
|
||||
@@ -102,94 +81,39 @@ class LVMShellProxy(object):
|
||||
assert (num_written == len(cmd_bytes))
|
||||
self.lvm_shell.stdin.flush()
|
||||
|
||||
def _lvm_echos(self):
|
||||
echo = False
|
||||
cmd = "version\n"
|
||||
self._write_cmd(cmd)
|
||||
line = self._read_line()
|
||||
|
||||
if line == cmd:
|
||||
echo = True
|
||||
|
||||
self._read_until_prompt()
|
||||
|
||||
return echo
|
||||
|
||||
def __init__(self):
|
||||
|
||||
# Create a temp directory
|
||||
tmp_dir = tempfile.mkdtemp(prefix="lvmdbus_")
|
||||
tmp_file = "%s/lvmdbus_report" % (tmp_dir)
|
||||
|
||||
try:
|
||||
# Lets create fifo for the report output
|
||||
os.mkfifo(tmp_file, 0o600)
|
||||
except FileExistsError:
|
||||
pass
|
||||
|
||||
self.report_r = os.open(tmp_file, os.O_NONBLOCK)
|
||||
|
||||
# Setup the environment for using our own socket for reporting
|
||||
local_env = copy.deepcopy(os.environ)
|
||||
local_env["LVM_REPORT_FD"] = "32"
|
||||
local_env["LVM_COMMAND_PROFILE"] = "lvmdbusd"
|
||||
|
||||
# Disable the abort logic if lvm logs too much, which easily happens
|
||||
# when utilizing the lvm shell.
|
||||
local_env["LVM_LOG_FILE_MAX_LINES"] = "0"
|
||||
|
||||
flags = fcntl(self.report_r, F_GETFL)
|
||||
fcntl(self.report_r, F_SETFL, flags | os.O_NONBLOCK)
|
||||
self.re = re.compile(".*(\[(-?[0-9]+)\] lvm> $)", re.DOTALL)
|
||||
|
||||
# run the lvm shell
|
||||
self.lvm_shell = subprocess.Popen(
|
||||
[LVM_CMD + " 32>%s" % tmp_file],
|
||||
stdin=subprocess.PIPE, stdout=subprocess.PIPE, env=local_env,
|
||||
stderr=subprocess.PIPE, close_fds=True, shell=True)
|
||||
[LVM_CMD], stdin=subprocess.PIPE, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE, close_fds=True)
|
||||
flags = fcntl(self.lvm_shell.stdout, F_GETFL)
|
||||
fcntl(self.lvm_shell.stdout, F_SETFL, flags | O_NONBLOCK)
|
||||
flags = fcntl(self.lvm_shell.stderr, F_GETFL)
|
||||
fcntl(self.lvm_shell.stderr, F_SETFL, flags | O_NONBLOCK)
|
||||
|
||||
try:
|
||||
flags = fcntl(self.lvm_shell.stdout, F_GETFL)
|
||||
fcntl(self.lvm_shell.stdout, F_SETFL, flags | os.O_NONBLOCK)
|
||||
flags = fcntl(self.lvm_shell.stderr, F_GETFL)
|
||||
fcntl(self.lvm_shell.stderr, F_SETFL, flags | os.O_NONBLOCK)
|
||||
# wait for the first prompt
|
||||
self._read_until_prompt()
|
||||
|
||||
# wait for the first prompt
|
||||
errors = self._read_until_prompt()[2]
|
||||
if errors and len(errors):
|
||||
raise RuntimeError(errors)
|
||||
except:
|
||||
raise
|
||||
finally:
|
||||
# These will get deleted when the FD count goes to zero so we can be
|
||||
# sure to clean up correctly no matter how we finish
|
||||
os.unlink(tmp_file)
|
||||
os.rmdir(tmp_dir)
|
||||
|
||||
def get_error_msg(self):
|
||||
# We got an error, lets go fetch the error message
|
||||
self._write_cmd('lastlog\n')
|
||||
|
||||
# read everything from the STDOUT to the next prompt
|
||||
stdout, report, stderr = self._read_until_prompt()
|
||||
|
||||
try:
|
||||
log = json.loads(report)
|
||||
|
||||
if 'log' in log:
|
||||
error_msg = ""
|
||||
# Walk the entire log array and build an error string
|
||||
for log_entry in log['log']:
|
||||
if log_entry['log_type'] == "error":
|
||||
if error_msg:
|
||||
error_msg += ', ' + log_entry['log_message']
|
||||
else:
|
||||
error_msg = log_entry['log_message']
|
||||
|
||||
return error_msg
|
||||
|
||||
return 'No error reason provided! (missing "log" section)'
|
||||
except ValueError:
|
||||
log_error("Invalid JSON returned from LVM")
|
||||
log_error("BEGIN>>\n%s\n<<END" % report)
|
||||
return "Invalid JSON returned from LVM when retrieving exit code"
|
||||
# Check to see if the version of LVM we are using is running with
|
||||
# gnu readline which will echo our writes from stdin to stdout
|
||||
self.echo = self._lvm_echos()
|
||||
|
||||
def call_lvm(self, argv, debug=False):
|
||||
rc = 1
|
||||
error_msg = ""
|
||||
json_result = ""
|
||||
|
||||
if self.lvm_shell.poll():
|
||||
raise Exception(
|
||||
self.lvm_shell.returncode,
|
||||
"Underlying lvm shell process is not present!")
|
||||
|
||||
# create the command string
|
||||
cmd = " ".join(_quote_arg(arg) for arg in argv)
|
||||
cmd += "\n"
|
||||
@@ -197,36 +121,46 @@ class LVMShellProxy(object):
|
||||
# run the command by writing it to the shell's STDIN
|
||||
self._write_cmd(cmd)
|
||||
|
||||
# read everything from the STDOUT to the next prompt
|
||||
stdout, report, stderr = self._read_until_prompt()
|
||||
# If lvm is utilizing gnu readline, it echos stdin to stdout
|
||||
if self.echo:
|
||||
self._discard_echo(cmd)
|
||||
|
||||
# Parse the report to see what happened
|
||||
if report and len(report):
|
||||
json_result = json.loads(report)
|
||||
if 'log' in json_result:
|
||||
if json_result['log'][-1:][0]['log_ret_code'] == '1':
|
||||
rc = 0
|
||||
else:
|
||||
error_msg = self.get_error_msg()
|
||||
# read everything from the STDOUT to the next prompt
|
||||
stdout, exit_code = self._read_until_prompt()
|
||||
|
||||
# read everything from STDERR if there's something (we waited for the
|
||||
# prompt on STDOUT so there should be all or nothing at this point on
|
||||
# STDERR)
|
||||
stderr = None
|
||||
try:
|
||||
t_error = self.lvm_shell.stderr.read()
|
||||
if t_error:
|
||||
stderr = t_error.decode("utf-8")
|
||||
except IOError:
|
||||
# nothing on STDERR
|
||||
pass
|
||||
|
||||
if exit_code is not None:
|
||||
rc = exit_code
|
||||
else:
|
||||
# LVM does write to stderr even when it did complete successfully,
|
||||
# so without having the exit code in the prompt we can never be
|
||||
# sure.
|
||||
if stderr:
|
||||
rc = 1
|
||||
else:
|
||||
rc = 0
|
||||
|
||||
if debug or rc != 0:
|
||||
log_error(('CMD: %s' % cmd))
|
||||
log_error(("EC = %d" % rc))
|
||||
log_error(("ERROR_MSG=\n %s\n" % error_msg))
|
||||
log_error(("STDOUT=\n %s\n" % stdout))
|
||||
log_error(("STDERR=\n %s\n" % stderr))
|
||||
|
||||
return rc, json_result, error_msg
|
||||
|
||||
def exit_shell(self):
|
||||
try:
|
||||
self._write_cmd('exit\n')
|
||||
except Exception as e:
|
||||
log_error(str(e))
|
||||
return (rc, stdout, stderr)
|
||||
|
||||
def __del__(self):
|
||||
try:
|
||||
self.lvm_shell.terminate()
|
||||
except:
|
||||
pass
|
||||
self.lvm_shell.terminate()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
@@ -236,15 +170,10 @@ if __name__ == "__main__":
|
||||
while in_line:
|
||||
in_line = input("lvm> ")
|
||||
if in_line:
|
||||
start = time.time()
|
||||
ret, out, err = shell.call_lvm(in_line.split())
|
||||
end = time.time()
|
||||
|
||||
print(("RC: %d" % ret))
|
||||
ret, out, err, = shell.call_lvm(in_line.split())
|
||||
print(("RET: %d" % ret))
|
||||
print(("OUT:\n%s" % out))
|
||||
print(("ERR:\n%s" % err))
|
||||
|
||||
print("Command = %f seconds" % (end - start))
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
except EOFError:
|
||||
|
@@ -12,15 +12,17 @@
|
||||
from collections import OrderedDict
|
||||
|
||||
import pprint as prettyprint
|
||||
import os
|
||||
import sys
|
||||
|
||||
from lvmdbusd import cmdhandler
|
||||
from lvmdbusd.utils import log_debug, log_error
|
||||
try:
|
||||
from . import cmdhandler
|
||||
from .utils import log_debug
|
||||
except SystemError:
|
||||
import cmdhandler
|
||||
from utils import log_debug
|
||||
|
||||
|
||||
class DataStore(object):
|
||||
def __init__(self, usejson=True):
|
||||
def __init__(self):
|
||||
self.pvs = {}
|
||||
self.vgs = {}
|
||||
self.lvs = {}
|
||||
@@ -38,11 +40,6 @@ class DataStore(object):
|
||||
# self.refresh()
|
||||
self.num_refreshes = 0
|
||||
|
||||
if usejson:
|
||||
self.json = cmdhandler.supports_json()
|
||||
else:
|
||||
self.json = usejson
|
||||
|
||||
@staticmethod
|
||||
def _insert_record(table, key, record, allowed_multiple):
|
||||
if key in table:
|
||||
@@ -79,58 +76,7 @@ class DataStore(object):
|
||||
for p in pvs:
|
||||
DataStore._insert_record(
|
||||
c_pvs, p['pv_uuid'], p,
|
||||
['pvseg_start', 'pvseg_size', 'segtype'])
|
||||
|
||||
for p in c_pvs.values():
|
||||
# Capture which PVs are associated with which VG
|
||||
if p['vg_uuid'] not in c_pvs_in_vgs:
|
||||
c_pvs_in_vgs[p['vg_uuid']] = []
|
||||
|
||||
if p['vg_name']:
|
||||
c_pvs_in_vgs[p['vg_uuid']].append(
|
||||
(p['pv_name'], p['pv_uuid']))
|
||||
|
||||
# Lookup for translating between /dev/<name> and pv uuid
|
||||
c_lookup[p['pv_name']] = p['pv_uuid']
|
||||
|
||||
return c_pvs, c_lookup, c_pvs_in_vgs
|
||||
|
||||
@staticmethod
|
||||
def _parse_pvs_json(_all):
|
||||
|
||||
c_pvs = OrderedDict()
|
||||
c_lookup = {}
|
||||
c_pvs_in_vgs = {}
|
||||
|
||||
# Each item item in the report is a collection of information pertaining
|
||||
# to the vg
|
||||
for r in _all['report']:
|
||||
tmp_pv = []
|
||||
|
||||
# Get the pv data for this VG.
|
||||
if 'pv' in r:
|
||||
tmp_pv.extend(r['pv'])
|
||||
|
||||
# Sort them
|
||||
sorted_tmp_pv = sorted(tmp_pv, key=lambda pk: pk['pv_name'])
|
||||
|
||||
# Add them to result set
|
||||
for p in sorted_tmp_pv:
|
||||
c_pvs[p['pv_uuid']] = p
|
||||
|
||||
if 'pvseg' in r:
|
||||
for s in r['pvseg']:
|
||||
r = c_pvs[s['pv_uuid']]
|
||||
r.setdefault('pvseg_start', []).append(s['pvseg_start'])
|
||||
r.setdefault('pvseg_size', []).append(s['pvseg_size'])
|
||||
r.setdefault('segtype', []).append(s['segtype'])
|
||||
|
||||
# TODO: Remove this bug work around when we have orphan segs.
|
||||
for i in c_pvs.values():
|
||||
if 'pvseg_start' not in i:
|
||||
i['pvseg_start'] = '0'
|
||||
i['pvseg_size'] = i['pv_pe_count']
|
||||
i['segtype'] = 'free'
|
||||
['pv_seg_start', 'pvseg_size', 'segtype'])
|
||||
|
||||
for p in c_pvs.values():
|
||||
# Capture which PVs are associated with which VG
|
||||
@@ -160,31 +106,20 @@ class DataStore(object):
|
||||
return c_vgs, c_lookup
|
||||
|
||||
@staticmethod
|
||||
def _parse_vgs_json(_all):
|
||||
def _parse_lvs(_lvs):
|
||||
lvs = sorted(_lvs, key=lambda vk: vk['lv_name'])
|
||||
|
||||
tmp_vg = []
|
||||
for r in _all['report']:
|
||||
# Get the pv data for this VG.
|
||||
if 'vg' in r:
|
||||
tmp_vg.extend(r['vg'])
|
||||
c_lvs = OrderedDict()
|
||||
c_lvs_in_vgs = {}
|
||||
c_lvs_hidden = {}
|
||||
c_lv_full_lookup = {}
|
||||
|
||||
# Sort for consistent output, however this is optional
|
||||
vgs = sorted(tmp_vg, key=lambda vk: vk['vg_name'])
|
||||
|
||||
c_vgs = OrderedDict()
|
||||
c_lookup = {}
|
||||
|
||||
for i in vgs:
|
||||
c_lookup[i['vg_name']] = i['vg_uuid']
|
||||
c_vgs[i['vg_uuid']] = i
|
||||
|
||||
return c_vgs, c_lookup
|
||||
|
||||
@staticmethod
|
||||
def _parse_lvs_common(c_lvs, c_lv_full_lookup):
|
||||
|
||||
c_lvs_in_vgs = OrderedDict()
|
||||
c_lvs_hidden = OrderedDict()
|
||||
for i in lvs:
|
||||
full_name = "%s/%s" % (i['vg_name'], i['lv_name'])
|
||||
c_lv_full_lookup[full_name] = i['lv_uuid']
|
||||
DataStore._insert_record(
|
||||
c_lvs, i['lv_uuid'], i,
|
||||
['seg_pe_ranges', 'segtype'])
|
||||
|
||||
for i in c_lvs.values():
|
||||
if i['vg_uuid'] not in c_lvs_in_vgs:
|
||||
@@ -214,48 +149,6 @@ class DataStore(object):
|
||||
|
||||
return c_lvs, c_lvs_in_vgs, c_lvs_hidden, c_lv_full_lookup
|
||||
|
||||
@staticmethod
|
||||
def _parse_lvs(_lvs):
|
||||
lvs = sorted(_lvs, key=lambda vk: vk['lv_name'])
|
||||
|
||||
c_lvs = OrderedDict()
|
||||
c_lv_full_lookup = OrderedDict()
|
||||
|
||||
for i in lvs:
|
||||
full_name = "%s/%s" % (i['vg_name'], i['lv_name'])
|
||||
c_lv_full_lookup[full_name] = i['lv_uuid']
|
||||
DataStore._insert_record(
|
||||
c_lvs, i['lv_uuid'], i,
|
||||
['seg_pe_ranges', 'segtype'])
|
||||
|
||||
return DataStore._parse_lvs_common(c_lvs, c_lv_full_lookup)
|
||||
|
||||
@staticmethod
|
||||
def _parse_lvs_json(_all):
|
||||
|
||||
c_lvs = OrderedDict()
|
||||
c_lv_full_lookup = {}
|
||||
|
||||
# Each item item in the report is a collection of information pertaining
|
||||
# to the vg
|
||||
for r in _all['report']:
|
||||
# Get the lv data for this VG.
|
||||
if 'lv' in r:
|
||||
# Add them to result set
|
||||
for i in r['lv']:
|
||||
full_name = "%s/%s" % (i['vg_name'], i['lv_name'])
|
||||
c_lv_full_lookup[full_name] = i['lv_uuid']
|
||||
c_lvs[i['lv_uuid']] = i
|
||||
|
||||
# Add in the segment data
|
||||
if 'seg' in r:
|
||||
for s in r['seg']:
|
||||
r = c_lvs[s['lv_uuid']]
|
||||
r.setdefault('seg_pe_ranges', []).append(s['seg_pe_ranges'])
|
||||
r.setdefault('segtype', []).append(s['segtype'])
|
||||
|
||||
return DataStore._parse_lvs_common(c_lvs, c_lv_full_lookup)
|
||||
|
||||
@staticmethod
|
||||
def _make_list(l):
|
||||
if not isinstance(l, list):
|
||||
@@ -379,27 +272,19 @@ class DataStore(object):
|
||||
:param log Add debug log entry/exit messages
|
||||
:return: None
|
||||
"""
|
||||
self.num_refreshes += 1
|
||||
|
||||
if log:
|
||||
log_debug("lvmdb - refresh entry")
|
||||
self.num_refreshes += 1
|
||||
|
||||
# Grab everything first then parse it
|
||||
if self.json:
|
||||
# Do a single lvm retrieve for everything in json
|
||||
a = cmdhandler.lvm_full_report_json()
|
||||
_raw_pvs = cmdhandler.pv_retrieve_with_segs()
|
||||
_raw_vgs = cmdhandler.vg_retrieve(None)
|
||||
_raw_lvs = cmdhandler.lv_retrieve_with_segments()
|
||||
|
||||
_pvs, _pvs_lookup, _pvs_in_vgs = self._parse_pvs_json(a)
|
||||
_vgs, _vgs_lookup = self._parse_vgs_json(a)
|
||||
_lvs, _lvs_in_vgs, _lvs_hidden, _lvs_lookup = self._parse_lvs_json(a)
|
||||
|
||||
else:
|
||||
_raw_pvs = cmdhandler.pv_retrieve_with_segs()
|
||||
_raw_vgs = cmdhandler.vg_retrieve(None)
|
||||
_raw_lvs = cmdhandler.lv_retrieve_with_segments()
|
||||
|
||||
_pvs, _pvs_lookup, _pvs_in_vgs = self._parse_pvs(_raw_pvs)
|
||||
_vgs, _vgs_lookup = self._parse_vgs(_raw_vgs)
|
||||
_lvs, _lvs_in_vgs, _lvs_hidden, _lvs_lookup = self._parse_lvs(_raw_lvs)
|
||||
_pvs, _pvs_lookup, _pvs_in_vgs = self._parse_pvs(_raw_pvs)
|
||||
_vgs, _vgs_lookup = self._parse_vgs(_raw_vgs)
|
||||
_lvs, _lvs_in_vgs, _lvs_hidden, _lvs_lookup = self._parse_lvs(_raw_lvs)
|
||||
|
||||
# Set all
|
||||
self.pvs = _pvs
|
||||
@@ -425,20 +310,9 @@ class DataStore(object):
|
||||
else:
|
||||
rc = []
|
||||
for s in pv_name:
|
||||
# Ths user could be using a symlink instead of the actual
|
||||
# block device, make sure we are using actual block device file
|
||||
# if the pv name isn't in the lookup
|
||||
if s not in self.pv_path_to_uuid:
|
||||
s = os.path.realpath(s)
|
||||
rc.append(self.pvs[self.pv_path_to_uuid[s]])
|
||||
return rc
|
||||
|
||||
def pv_missing(self, pv_uuid):
|
||||
if pv_uuid in self.pvs:
|
||||
if self.pvs[pv_uuid]['pv_missing'] == '':
|
||||
return False
|
||||
return True
|
||||
|
||||
def fetch_vgs(self, vg_name):
|
||||
if not vg_name:
|
||||
return self.vgs.values()
|
||||
@@ -458,18 +332,18 @@ class DataStore(object):
|
||||
rc.append(self.lvs[self.lv_full_name_to_uuid[s]])
|
||||
return rc
|
||||
except KeyError as ke:
|
||||
log_error("Key %s not found!" % (str(lv_names)))
|
||||
log_error("lv name to uuid lookup")
|
||||
print("Key %s not found!" % (str(lv_names)))
|
||||
print("lv name to uuid lookup")
|
||||
for keys in sorted(self.lv_full_name_to_uuid.keys()):
|
||||
log_error("%s" % (keys))
|
||||
log_error("lvs entries by uuid")
|
||||
print("%s" % (keys))
|
||||
print("lvs entries by uuid")
|
||||
for keys in sorted(self.lvs.keys()):
|
||||
log_error("%s" % (keys))
|
||||
print("%s" % (keys))
|
||||
raise ke
|
||||
|
||||
def pv_pe_segments(self, pv_uuid):
|
||||
pv = self.pvs[pv_uuid]
|
||||
return list(zip(pv['pvseg_start'], pv['pvseg_size']))
|
||||
return list(zip(pv['pv_seg_start'], pv['pvseg_size']))
|
||||
|
||||
def pv_contained_lv(self, pv_device):
|
||||
rc = []
|
||||
@@ -510,21 +384,12 @@ class DataStore(object):
|
||||
if __name__ == "__main__":
|
||||
pp = prettyprint.PrettyPrinter(indent=4)
|
||||
|
||||
use_json = False
|
||||
|
||||
if len(sys.argv) != 1:
|
||||
print(len(sys.argv))
|
||||
use_json = True
|
||||
|
||||
ds = DataStore(use_json)
|
||||
ds = DataStore()
|
||||
ds.refresh()
|
||||
|
||||
print("PVS")
|
||||
for v in ds.pvs.values():
|
||||
pp.pprint(v)
|
||||
print('PV missing is %s' % ds.pv_missing(v['pv_uuid']))
|
||||
|
||||
print("VGS")
|
||||
for v in ds.vgs.values():
|
||||
pp.pprint(v)
|
||||
|
||||
|
@@ -10,7 +10,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import sys
|
||||
from lvmdbusd import main
|
||||
import lvmdbusd
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
sys.exit(lvmdbusd.main())
|
||||
|
@@ -16,21 +16,18 @@ from . import cmdhandler
|
||||
import time
|
||||
import signal
|
||||
import dbus
|
||||
import dbus.mainloop.glib
|
||||
from . import lvmdb
|
||||
# noinspection PyUnresolvedReferences
|
||||
from gi.repository import GLib
|
||||
from gi.repository import GObject
|
||||
from .fetch import load
|
||||
from .manager import Manager
|
||||
from .background import background_reaper
|
||||
import traceback
|
||||
import queue
|
||||
from . import udevwatch
|
||||
from .utils import log_debug, log_error
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
from .refresh import handle_external_event, event_complete
|
||||
from . import udevwatch
|
||||
from .utils import log_debug
|
||||
import argparse
|
||||
|
||||
|
||||
class Lvm(objectmanager.ObjectManager):
|
||||
@@ -38,30 +35,6 @@ class Lvm(objectmanager.ObjectManager):
|
||||
super(Lvm, self).__init__(object_path, BASE_INTERFACE)
|
||||
|
||||
|
||||
def _discard_pending_refreshes():
|
||||
# We just handled a refresh, if we have any in the queue they can be
|
||||
# removed because by definition they are older than the refresh we just did.
|
||||
# As we limit the number of refreshes getting into the queue
|
||||
# we should only ever have one to remove.
|
||||
requests = []
|
||||
while not cfg.worker_q.empty():
|
||||
try:
|
||||
r = cfg.worker_q.get(block=False)
|
||||
if r.method != handle_external_event:
|
||||
requests.append(r)
|
||||
else:
|
||||
# Make sure we make this event complete even though it didn't
|
||||
# run, otherwise no other events will get processed
|
||||
event_complete()
|
||||
break
|
||||
except queue.Empty:
|
||||
break
|
||||
|
||||
# Any requests we removed, but did not discard need to be re-queued
|
||||
for r in requests:
|
||||
cfg.worker_q.put(r)
|
||||
|
||||
|
||||
def process_request():
|
||||
while cfg.run.value != 0:
|
||||
try:
|
||||
@@ -76,62 +49,37 @@ def process_request():
|
||||
|
||||
end = cfg.db.num_refreshes
|
||||
|
||||
num_refreshes = end - start
|
||||
|
||||
if num_refreshes > 0:
|
||||
_discard_pending_refreshes()
|
||||
|
||||
if num_refreshes > 1:
|
||||
log_debug(
|
||||
"Inspect method %s for too many refreshes" %
|
||||
(str(req.method)))
|
||||
if end - start > 1:
|
||||
log_debug(
|
||||
"Inspect method %s for too many refreshes" %
|
||||
(str(req.method)))
|
||||
log_debug("Complete ")
|
||||
except queue.Empty:
|
||||
pass
|
||||
except Exception:
|
||||
st = traceback.format_exc()
|
||||
utils.log_error("process_request exception: \n%s" % st)
|
||||
traceback.print_exc(file=sys.stdout)
|
||||
pass
|
||||
|
||||
|
||||
def main():
|
||||
start = time.time()
|
||||
# Add simple command line handling
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"--udev", action='store_true',
|
||||
help="Use udev for updating state",
|
||||
default=False,
|
||||
dest='use_udev')
|
||||
parser.add_argument(
|
||||
"--debug", action='store_true',
|
||||
help="Dump debug messages", default=False,
|
||||
dest='debug')
|
||||
parser.add_argument(
|
||||
"--nojson", action='store_false',
|
||||
help="Do not use LVM JSON output (disables lvmshell)", default=True,
|
||||
dest='use_json')
|
||||
parser.add_argument(
|
||||
"--lvmshell", action='store_true',
|
||||
help="Use the lvm shell, not fork & exec lvm",
|
||||
default=False,
|
||||
dest='use_lvm_shell')
|
||||
parser.add_argument("--udev", action='store_true',
|
||||
help="Use udev for updating state", default=False,
|
||||
dest='use_udev')
|
||||
parser.add_argument("--debug", action='store_true',
|
||||
help="Dump debug messages", default=False,
|
||||
dest='debug')
|
||||
|
||||
use_session = os.getenv('LVMDBUSD_USE_SESSION', False)
|
||||
args = parser.parse_args()
|
||||
|
||||
# Ensure that we get consistent output for parsing stdout/stderr
|
||||
os.environ["LC_ALL"] = "C"
|
||||
|
||||
cfg.args = parser.parse_args()
|
||||
|
||||
if cfg.args.use_lvm_shell and not cfg.args.use_json:
|
||||
log_error("You cannot specify --lvmshell and --nojson")
|
||||
sys.exit(1)
|
||||
|
||||
cmdhandler.set_execution(cfg.args.use_lvm_shell)
|
||||
cfg.DEBUG = args.debug
|
||||
|
||||
# List of threads that we start up
|
||||
thread_list = []
|
||||
|
||||
start = time.time()
|
||||
|
||||
# Install signal handlers
|
||||
for s in [signal.SIGHUP, signal.SIGINT]:
|
||||
try:
|
||||
@@ -140,12 +88,9 @@ def main():
|
||||
pass
|
||||
|
||||
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
|
||||
GObject.threads_init()
|
||||
dbus.mainloop.glib.threads_init()
|
||||
|
||||
if use_session:
|
||||
cfg.bus = dbus.SessionBus()
|
||||
else:
|
||||
cfg.bus = dbus.SystemBus()
|
||||
cfg.bus = dbus.SystemBus()
|
||||
# The base name variable needs to exist for things to work.
|
||||
# noinspection PyUnusedLocal
|
||||
base_name = dbus.service.BusName(BASE_INTERFACE, cfg.bus)
|
||||
@@ -154,7 +99,7 @@ def main():
|
||||
|
||||
cfg.load = load
|
||||
|
||||
cfg.db = lvmdb.DataStore(cfg.args.use_json)
|
||||
cfg.db = lvmdb.DataStore()
|
||||
|
||||
# Start up thread to monitor pv moves
|
||||
thread_list.append(
|
||||
@@ -164,31 +109,29 @@ def main():
|
||||
thread_list.append(threading.Thread(target=process_request))
|
||||
|
||||
cfg.load(refresh=False, emit_signal=False)
|
||||
cfg.loop = GLib.MainLoop()
|
||||
cfg.loop = GObject.MainLoop()
|
||||
|
||||
for process in thread_list:
|
||||
process.damon = True
|
||||
process.start()
|
||||
|
||||
# Add udev watching
|
||||
if cfg.args.use_udev:
|
||||
log_debug('Utilizing udev to trigger updates')
|
||||
|
||||
# In all cases we are going to monitor for udev until we get an
|
||||
# ExternalEvent. In the case where we get an external event and the user
|
||||
# didn't specify --udev we will stop monitoring udev
|
||||
udevwatch.add()
|
||||
|
||||
end = time.time()
|
||||
log_debug(
|
||||
'Service ready! total time= %.4f, lvm time= %.4f count= %d' %
|
||||
'Service ready! total time= %.2f, lvm time= %.2f count= %d' %
|
||||
(end - start, cmdhandler.total_time, cmdhandler.total_count),
|
||||
'bg_black', 'fg_light_green')
|
||||
|
||||
# Add udev watching
|
||||
if args.use_udev:
|
||||
log_debug('Utilizing udev to trigger updates')
|
||||
udevwatch.add()
|
||||
|
||||
try:
|
||||
if cfg.run.value != 0:
|
||||
cfg.loop.run()
|
||||
udevwatch.remove()
|
||||
|
||||
if args.use_udev:
|
||||
udevwatch.remove()
|
||||
|
||||
for process in thread_list:
|
||||
process.join()
|
||||
|
@@ -17,12 +17,11 @@ from . import cmdhandler
|
||||
from .fetch import load_pvs, load_vgs
|
||||
from .request import RequestEntry
|
||||
from .refresh import event_add
|
||||
from . import udevwatch
|
||||
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
class Manager(AutomatedProperties):
|
||||
_Version_meta = ("s", MANAGER_INTERFACE)
|
||||
_Version_meta = ("t", MANAGER_INTERFACE)
|
||||
|
||||
def __init__(self, object_path):
|
||||
super(Manager, self).__init__(object_path)
|
||||
@@ -30,14 +29,15 @@ class Manager(AutomatedProperties):
|
||||
|
||||
@property
|
||||
def Version(self):
|
||||
return dbus.String('1.0.0')
|
||||
return '1.0.0'
|
||||
|
||||
@staticmethod
|
||||
def _pv_create(device, create_options):
|
||||
|
||||
# Check to see if we are already trying to create a PV for an existing
|
||||
# PV
|
||||
pv = cfg.om.get_object_path_by_uuid_lvm_id(device, device)
|
||||
pv = cfg.om.get_object_path_by_lvm_id(
|
||||
device, device, None, False)
|
||||
if pv:
|
||||
raise dbus.exceptions.DBusException(
|
||||
MANAGER_INTERFACE, "PV Already exists!")
|
||||
@@ -114,10 +114,6 @@ class Manager(AutomatedProperties):
|
||||
|
||||
# This is a diagnostic and should not be run in normal operation, so
|
||||
# lets remove the log entries for refresh as it's implied.
|
||||
|
||||
# Run an internal diagnostic on the object manager look up tables
|
||||
lc = cfg.om.validate_lookups()
|
||||
|
||||
rc = cfg.load(log=False)
|
||||
|
||||
if rc != 0:
|
||||
@@ -125,7 +121,7 @@ class Manager(AutomatedProperties):
|
||||
'bg_black', 'fg_light_red')
|
||||
else:
|
||||
utils.log_debug('Manager.Refresh - exit %d' % (rc))
|
||||
return rc + lc
|
||||
return rc
|
||||
|
||||
@dbus.service.method(
|
||||
dbus_interface=MANAGER_INTERFACE,
|
||||
@@ -163,34 +159,28 @@ class Manager(AutomatedProperties):
|
||||
:param key: The lookup value
|
||||
:return: Return the object path. If object not found you will get '/'
|
||||
"""
|
||||
p = cfg.om.get_object_path_by_uuid_lvm_id(key, key)
|
||||
p = cfg.om.get_object_path_by_lvm_id(
|
||||
key, key, gen_new=False)
|
||||
if p:
|
||||
return p
|
||||
return '/'
|
||||
|
||||
@dbus.service.method(
|
||||
dbus_interface=MANAGER_INTERFACE,
|
||||
in_signature='b', out_signature='b')
|
||||
in_signature='b')
|
||||
def UseLvmShell(self, yes_no):
|
||||
"""
|
||||
Allow the client to enable/disable lvm shell, used for testing
|
||||
:param yes_no:
|
||||
:return: Nothing
|
||||
"""
|
||||
return dbus.Boolean(cmdhandler.set_execution(yes_no))
|
||||
cmdhandler.set_execution(yes_no)
|
||||
|
||||
@dbus.service.method(
|
||||
dbus_interface=MANAGER_INTERFACE,
|
||||
in_signature='s', out_signature='i')
|
||||
def ExternalEvent(self, command):
|
||||
|
||||
# If a user didn't explicitly specify udev, we will turn it off now.
|
||||
if not cfg.args.use_udev:
|
||||
if udevwatch.remove():
|
||||
utils.log_debug("ExternalEvent received, disabling "
|
||||
"udev monitoring")
|
||||
# We are dependent on external events now to stay current!
|
||||
cfg.ee = True
|
||||
event_add((command,))
|
||||
return dbus.Int32(0)
|
||||
|
||||
|
@@ -11,10 +11,8 @@ import sys
|
||||
import threading
|
||||
import traceback
|
||||
import dbus
|
||||
import os
|
||||
import copy
|
||||
from . import cfg
|
||||
from .utils import log_debug, pv_obj_path_generate, log_error
|
||||
from .utils import log_debug
|
||||
from .automatedproperties import AutomatedProperties
|
||||
|
||||
|
||||
@@ -71,37 +69,12 @@ class ObjectManager(AutomatedProperties):
|
||||
log_debug(('SIGNAL: InterfacesRemoved(%s, %s)' %
|
||||
(str(object_path), str(interface_list))))
|
||||
|
||||
def validate_lookups(self):
|
||||
with self.rlock:
|
||||
tmp_lookups = copy.deepcopy(self._id_to_object_path)
|
||||
|
||||
# iterate over all we know, removing from the copy. If all is well
|
||||
# we will have zero items left over
|
||||
for path, md in self._objects.items():
|
||||
obj, lvm_id, uuid = md
|
||||
|
||||
if lvm_id:
|
||||
assert path == tmp_lookups[lvm_id]
|
||||
del tmp_lookups[lvm_id]
|
||||
|
||||
if uuid:
|
||||
assert path == tmp_lookups[uuid]
|
||||
del tmp_lookups[uuid]
|
||||
|
||||
rc = len(tmp_lookups)
|
||||
if rc:
|
||||
# Error condition
|
||||
log_error("_id_to_object_path has extraneous lookups!")
|
||||
for key, path in tmp_lookups.items():
|
||||
log_error("Key= %s, path= %s" % (key, path))
|
||||
return rc
|
||||
|
||||
def _lookup_add(self, obj, path, lvm_id, uuid):
|
||||
"""
|
||||
Store information about what we added to the caches so that we
|
||||
can remove it cleanly
|
||||
:param obj: The dbus object we are storing
|
||||
:param lvm_id: The lvm id for the asset
|
||||
:param lvm_id: The user name for the asset
|
||||
:param uuid: The uuid for the asset
|
||||
:return:
|
||||
"""
|
||||
@@ -111,12 +84,7 @@ class ObjectManager(AutomatedProperties):
|
||||
self._lookup_remove(path)
|
||||
|
||||
self._objects[path] = (obj, lvm_id, uuid)
|
||||
|
||||
# Make sure we have one or the other
|
||||
assert lvm_id or uuid
|
||||
|
||||
if lvm_id:
|
||||
self._id_to_object_path[lvm_id] = path
|
||||
self._id_to_object_path[lvm_id] = path
|
||||
|
||||
if uuid:
|
||||
self._id_to_object_path[uuid] = path
|
||||
@@ -125,13 +93,8 @@ class ObjectManager(AutomatedProperties):
|
||||
# Note: Only called internally, lock implied
|
||||
if obj_path in self._objects:
|
||||
(obj, lvm_id, uuid) = self._objects[obj_path]
|
||||
|
||||
if lvm_id in self._id_to_object_path:
|
||||
del self._id_to_object_path[lvm_id]
|
||||
|
||||
if uuid in self._id_to_object_path:
|
||||
del self._id_to_object_path[uuid]
|
||||
|
||||
del self._id_to_object_path[lvm_id]
|
||||
del self._id_to_object_path[uuid]
|
||||
del self._objects[obj_path]
|
||||
|
||||
def lookup_update(self, dbus_obj, new_uuid, new_lvm_id):
|
||||
@@ -160,8 +123,8 @@ class ObjectManager(AutomatedProperties):
|
||||
with self.rlock:
|
||||
path, props = dbus_object.emit_data()
|
||||
|
||||
# print('Registering object path %s for %s' %
|
||||
# (path, dbus_object.lvm_id))
|
||||
# print 'Registering object path %s for %s' %
|
||||
# (path, dbus_object.lvm_id)
|
||||
|
||||
# We want fast access to the object by a number of different ways
|
||||
# so we use multiple hashs with different keys
|
||||
@@ -209,7 +172,7 @@ class ObjectManager(AutomatedProperties):
|
||||
def get_object_by_uuid_lvm_id(self, uuid, lvm_id):
|
||||
with self.rlock:
|
||||
return self.get_object_by_path(
|
||||
self.get_object_path_by_uuid_lvm_id(uuid, lvm_id))
|
||||
self.get_object_path_by_lvm_id(uuid, lvm_id, None, False))
|
||||
|
||||
def get_object_by_lvm_id(self, lvm_id):
|
||||
"""
|
||||
@@ -221,132 +184,74 @@ class ObjectManager(AutomatedProperties):
|
||||
return self.get_object_by_path(self._id_to_object_path[lvm_id])
|
||||
return None
|
||||
|
||||
def get_object_path_by_lvm_id(self, lvm_id):
|
||||
"""
|
||||
Given an lvm identifier, return the object path for it
|
||||
:param lvm_id: The lvm identifier
|
||||
:return: Object path or '/' if not found
|
||||
"""
|
||||
with self.rlock:
|
||||
if lvm_id in self._id_to_object_path:
|
||||
return self._id_to_object_path[lvm_id]
|
||||
return '/'
|
||||
|
||||
def _uuid_verify(self, path, uuid, lvm_id):
|
||||
def _uuid_verify(self, path, lvm_id, uuid):
|
||||
"""
|
||||
Ensure uuid is present for a successful lvm_id lookup
|
||||
NOTE: Internal call, assumes under object manager lock
|
||||
:param path: Path to object we looked up
|
||||
:param uuid: lvm uuid to verify
|
||||
:param lvm_id: lvm_id used to find object
|
||||
:param uuid: lvm uuid to verify
|
||||
:return: None
|
||||
"""
|
||||
# This gets called when we found an object based on lvm_id, ensure
|
||||
# uuid is correct too, as they can change. There is no durable
|
||||
# non-changeable name in lvm
|
||||
# uuid is correct too, as they can change
|
||||
if lvm_id != uuid:
|
||||
if uuid and uuid not in self._id_to_object_path:
|
||||
if uuid not in self._id_to_object_path:
|
||||
obj = self.get_object_by_path(path)
|
||||
self._lookup_add(obj, path, lvm_id, uuid)
|
||||
|
||||
def _lvm_id_verify(self, path, uuid, lvm_id):
|
||||
def get_object_path_by_lvm_id(self, uuid, lvm_id, path_create=None,
|
||||
gen_new=True):
|
||||
"""
|
||||
Ensure lvm_id is present for a successful uuid lookup
|
||||
NOTE: Internal call, assumes under object manager lock
|
||||
:param path: Path to object we looked up
|
||||
:param uuid: uuid used to find object
|
||||
:param lvm_id: lvm_id to verify
|
||||
:return: None
|
||||
"""
|
||||
# This gets called when we found an object based on uuid, ensure
|
||||
# lvm_id is correct too, as they can change. There is no durable
|
||||
# non-changeable name in lvm
|
||||
if lvm_id != uuid:
|
||||
if lvm_id and lvm_id not in self._id_to_object_path:
|
||||
obj = self.get_object_by_path(path)
|
||||
self._lookup_add(obj, path, lvm_id, uuid)
|
||||
|
||||
def _id_lookup(self, the_id):
|
||||
path = None
|
||||
|
||||
if the_id:
|
||||
# The _id_to_object_path contains hash keys for everything, so
|
||||
# uuid and lvm_id
|
||||
if the_id in self._id_to_object_path:
|
||||
path = self._id_to_object_path[the_id]
|
||||
else:
|
||||
if "/" in the_id:
|
||||
if the_id.startswith('/'):
|
||||
# We could have a pv device path lookup that failed,
|
||||
# lets try canonical form and try again.
|
||||
canonical = os.path.realpath(the_id)
|
||||
if canonical in self._id_to_object_path:
|
||||
path = self._id_to_object_path[canonical]
|
||||
else:
|
||||
vg, lv = the_id.split("/", 1)
|
||||
int_lvm_id = vg + "/" + ("[%s]" % lv)
|
||||
if int_lvm_id in self._id_to_object_path:
|
||||
path = self._id_to_object_path[int_lvm_id]
|
||||
return path
|
||||
|
||||
def get_object_path_by_uuid_lvm_id(self, uuid, lvm_id, path_create=None):
|
||||
"""
|
||||
For a given lvm asset return the dbus object path registered for it.
|
||||
This method first looks up by uuid and then by lvm_id. You
|
||||
can search by just one by setting uuid == lvm_id (uuid or lvm_id).
|
||||
If the object is not found and path_create is a not None, the
|
||||
path_create function will be called to create a new object path and
|
||||
register it with the object manager for the specified uuid & lvm_id.
|
||||
Note: If path create is not None, uuid and lvm_id cannot be equal
|
||||
:param uuid: The uuid for the lvm object we are searching for
|
||||
:param lvm_id: The lvm name (eg. pv device path, vg name, lv full name)
|
||||
:param path_create: If not None, create the path using this function if
|
||||
we fail to find the object by uuid or lvm_id.
|
||||
:returns None if lvm asset not found and path_create == None otherwise
|
||||
a valid dbus object path
|
||||
For a given lvm asset return the dbus object registered to it. If the
|
||||
object is not found and gen_new == True and path_create is a valid
|
||||
function we will create a new path, register it and return it.
|
||||
:param uuid: The uuid for the lvm object
|
||||
:param lvm_id: The lvm name
|
||||
:param path_create: If true create an object path if not found
|
||||
:param gen_new: The function used to create the new path
|
||||
"""
|
||||
with self.rlock:
|
||||
assert lvm_id
|
||||
assert uuid
|
||||
|
||||
if path_create:
|
||||
assert uuid != lvm_id
|
||||
if gen_new:
|
||||
assert path_create
|
||||
|
||||
# Check for Manager.LookUpByLvmId query, we cannot
|
||||
# check/verify/update the uuid and lvm_id lookups so don't!
|
||||
if uuid == lvm_id:
|
||||
path = self._id_lookup(lvm_id)
|
||||
path = None
|
||||
|
||||
if lvm_id in self._id_to_object_path:
|
||||
path = self._id_to_object_path[lvm_id]
|
||||
self._uuid_verify(path, lvm_id, uuid)
|
||||
return path
|
||||
if "/" in lvm_id:
|
||||
vg, lv = lvm_id.split("/", 1)
|
||||
int_lvm_id = vg + "/" + ("[%s]" % lv)
|
||||
if int_lvm_id in self._id_to_object_path:
|
||||
path = self._id_to_object_path[int_lvm_id]
|
||||
self._uuid_verify(path, int_lvm_id, uuid)
|
||||
return path
|
||||
|
||||
if uuid and uuid in self._id_to_object_path:
|
||||
# If we get here it indicates that we found the object, but
|
||||
# the lvm_id lookup failed. In the case of a rename, the uuid
|
||||
# will be correct, but the lvm_id will be wrong and vise versa.
|
||||
# If the lvm_id does not equal the uuid, lets fix up the table
|
||||
# so that lookups will be handled correctly.
|
||||
path = self._id_to_object_path[uuid]
|
||||
|
||||
# In some cases we are looking up by one or the other, don't
|
||||
# update when they are the same.
|
||||
if uuid != lvm_id:
|
||||
obj = self.get_object_by_path(path)
|
||||
self._lookup_add(obj, path, lvm_id, uuid)
|
||||
else:
|
||||
# We have a uuid and a lvm_id we can do sanity checks to ensure
|
||||
# that they are consistent
|
||||
if gen_new:
|
||||
path = path_create()
|
||||
self._lookup_add(None, path, lvm_id, uuid)
|
||||
|
||||
# If a PV is missing it's device path is '[unknown]' or some
|
||||
# other text derivation of unknown. When we find that a PV is
|
||||
# missing we will clear out the lvm_id as it's likely not unique
|
||||
# and thus not useful and potentially harmful for lookups.
|
||||
if path_create == pv_obj_path_generate and \
|
||||
cfg.db.pv_missing(uuid):
|
||||
lvm_id = None
|
||||
|
||||
# Lets check for the uuid first
|
||||
path = self._id_lookup(uuid)
|
||||
if path:
|
||||
# Verify the lvm_id is sane
|
||||
self._lvm_id_verify(path, uuid, lvm_id)
|
||||
else:
|
||||
# Unable to find by UUID, lets lookup by lvm_id
|
||||
path = self._id_lookup(lvm_id)
|
||||
if path:
|
||||
# Verify the uuid is sane
|
||||
self._uuid_verify(path, uuid, lvm_id)
|
||||
else:
|
||||
# We have exhausted all lookups, let's create if we can
|
||||
if path_create:
|
||||
path = path_create()
|
||||
self._lookup_add(None, path, lvm_id, uuid)
|
||||
|
||||
# print('get_object_path_by_lvm_id(%s, %s, %s, %s: return %s' %
|
||||
# (uuid, lvm_id, str(path_create), str(gen_new), path))
|
||||
# pprint('get_object_path_by_lvm_id(%s, %s, %s, %s: return %s' %
|
||||
# (uuid, lvm_id, str(path_create), str(gen_new), path))
|
||||
|
||||
return path
|
||||
|
||||
|
@@ -55,6 +55,9 @@ class PvState(State):
|
||||
return self.lvm_path
|
||||
|
||||
def _lv_object_list(self, vg_name):
|
||||
|
||||
# Note we are returning "a(oa(tts))"
|
||||
|
||||
rc = []
|
||||
if vg_name:
|
||||
for lv in sorted(cfg.db.pv_contained_lv(self.lvm_id)):
|
||||
@@ -62,11 +65,11 @@ class PvState(State):
|
||||
full_name = "%s/%s" % (vg_name, lv_name)
|
||||
|
||||
path_create = lv_object_path_method(lv_name, meta)
|
||||
lv_path = cfg.om.get_object_path_by_uuid_lvm_id(
|
||||
lv_path = cfg.om.get_object_path_by_lvm_id(
|
||||
lv_uuid, full_name, path_create)
|
||||
|
||||
rc.append((lv_path, segs))
|
||||
return rc
|
||||
return dbus.Array(rc, signature="(oa(tts))")
|
||||
|
||||
# noinspection PyUnusedLocal,PyPep8Naming
|
||||
def __init__(self, lvm_path, Uuid, Name,
|
||||
@@ -80,7 +83,7 @@ class PvState(State):
|
||||
self.lv = self._lv_object_list(vg_name)
|
||||
|
||||
if vg_name:
|
||||
self.vg_path = cfg.om.get_object_path_by_uuid_lvm_id(
|
||||
self.vg_path = cfg.om.get_object_path_by_lvm_id(
|
||||
vg_uuid, vg_name, vg_obj_path_generate)
|
||||
else:
|
||||
self.vg_path = '/'
|
||||
@@ -90,8 +93,8 @@ class PvState(State):
|
||||
|
||||
def create_dbus_object(self, path):
|
||||
if not path:
|
||||
path = cfg.om.get_object_path_by_uuid_lvm_id(self.Uuid, self.Name,
|
||||
pv_obj_path_generate)
|
||||
path = cfg.om.get_object_path_by_lvm_id(self.Uuid, self.Name,
|
||||
pv_obj_path_generate)
|
||||
return Pv(path, self)
|
||||
|
||||
# noinspection PyMethodMayBeStatic
|
||||
@@ -238,20 +241,26 @@ class Pv(AutomatedProperties):
|
||||
@property
|
||||
def PeSegments(self):
|
||||
if len(self.state.pe_segments):
|
||||
return dbus.Array(self.state.pe_segments, signature='(tt)')
|
||||
return self.state.pe_segments
|
||||
return dbus.Array([], '(tt)')
|
||||
|
||||
@property
|
||||
def Exportable(self):
|
||||
return dbus.Boolean(self.state.attr[1] == 'x')
|
||||
if self.state.attr[1] == 'x':
|
||||
return True
|
||||
return False
|
||||
|
||||
@property
|
||||
def Allocatable(self):
|
||||
return dbus.Boolean(self.state.attr[0] == 'a')
|
||||
if self.state.attr[0] == 'a':
|
||||
return True
|
||||
return False
|
||||
|
||||
@property
|
||||
def Missing(self):
|
||||
return dbus.Boolean(self.state.attr[2] == 'm')
|
||||
if self.state.attr[2] == 'm':
|
||||
return True
|
||||
return False
|
||||
|
||||
def object_path(self):
|
||||
return self._object_path
|
||||
@@ -266,8 +275,8 @@ class Pv(AutomatedProperties):
|
||||
|
||||
@property
|
||||
def Lv(self):
|
||||
return dbus.Array(self.state.lv, signature="(oa(tts))")
|
||||
return self.state.lv
|
||||
|
||||
@property
|
||||
def Vg(self):
|
||||
return dbus.ObjectPath(self.state.vg_path)
|
||||
return self.state.vg_path
|
||||
|
@@ -9,7 +9,7 @@
|
||||
|
||||
import threading
|
||||
# noinspection PyUnresolvedReferences
|
||||
from gi.repository import GLib
|
||||
from gi.repository import GObject
|
||||
from .job import Job
|
||||
from . import cfg
|
||||
import traceback
|
||||
@@ -18,7 +18,7 @@ from .utils import log_error
|
||||
|
||||
class RequestEntry(object):
|
||||
def __init__(self, tmo, method, arguments, cb, cb_error,
|
||||
return_tuple=True, job_state=None):
|
||||
return_tuple=True):
|
||||
self.tmo = tmo
|
||||
self.method = method
|
||||
self.arguments = arguments
|
||||
@@ -29,11 +29,10 @@ class RequestEntry(object):
|
||||
self.lock = threading.RLock()
|
||||
self.done = False
|
||||
self._result = None
|
||||
self._job = None
|
||||
self._job = False
|
||||
self._rc = 0
|
||||
self._rc_error = None
|
||||
self._return_tuple = return_tuple
|
||||
self._job_state = job_state
|
||||
|
||||
if self.tmo < 0:
|
||||
# Client is willing to block forever
|
||||
@@ -41,7 +40,7 @@ class RequestEntry(object):
|
||||
elif tmo == 0:
|
||||
self._return_job()
|
||||
else:
|
||||
self.timer_id = GLib.timeout_add_seconds(
|
||||
self.timer_id = GObject.timeout_add_seconds(
|
||||
tmo, RequestEntry._request_timeout, self)
|
||||
|
||||
@staticmethod
|
||||
@@ -54,7 +53,7 @@ class RequestEntry(object):
|
||||
r.timer_expired()
|
||||
|
||||
def _return_job(self):
|
||||
self._job = Job(self, self._job_state)
|
||||
self._job = Job(self)
|
||||
cfg.om.register_object(self._job, True)
|
||||
if self._return_tuple:
|
||||
self.cb(('/', self._job.dbus_object_path()))
|
||||
@@ -65,14 +64,13 @@ class RequestEntry(object):
|
||||
try:
|
||||
result = self.method(*self.arguments)
|
||||
self.register_result(result)
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
# Use the request entry to return the result as the client may
|
||||
# have gotten a job by the time we hit an error
|
||||
# Lets get the stacktrace and set that to the error message
|
||||
st = traceback.format_exc()
|
||||
cfg.blackbox.dump()
|
||||
log_error("Exception returned to client: \n%s" % st)
|
||||
self.register_error(-1, str(e), e)
|
||||
self.register_error(-1, st)
|
||||
|
||||
def is_done(self):
|
||||
with self.lock:
|
||||
@@ -89,17 +87,16 @@ class RequestEntry(object):
|
||||
return self._result
|
||||
return '/'
|
||||
|
||||
def _reg_ending(self, result, error_rc=0, error_msg=None,
|
||||
error_exception=None):
|
||||
def _reg_ending(self, result, error_rc=0, error=None):
|
||||
with self.lock:
|
||||
self.done = True
|
||||
if self.timer_id != -1:
|
||||
# Try to prevent the timer from firing
|
||||
GLib.source_remove(self.timer_id)
|
||||
GObject.source_remove(self.timer_id)
|
||||
|
||||
self._result = result
|
||||
self._rc = error_rc
|
||||
self._rc_error = error_msg
|
||||
self._rc_error = error
|
||||
|
||||
if not self._job:
|
||||
# We finished and there is no job, so return result or error
|
||||
@@ -115,23 +112,15 @@ class RequestEntry(object):
|
||||
self.cb(result)
|
||||
else:
|
||||
if self.cb_error:
|
||||
if not error_exception:
|
||||
if not error_msg:
|
||||
error_exception = Exception(
|
||||
"An error occurred, but no reason was "
|
||||
"given, see service logs!")
|
||||
else:
|
||||
error_exception = Exception(error_msg)
|
||||
|
||||
self.cb_error(error_exception)
|
||||
self.cb_error(self._rc_error)
|
||||
else:
|
||||
# We have a job and it's complete, indicate that it's done.
|
||||
# TODO: We need to signal the job is done too.
|
||||
self._job.Complete = True
|
||||
self._job = None
|
||||
|
||||
def register_error(self, error_rc, error_message, error_exception):
|
||||
self._reg_ending('/', error_rc, error_message, error_exception)
|
||||
def register_error(self, error_rc, error):
|
||||
self._reg_ending(None, error_rc, error)
|
||||
|
||||
def register_result(self, result):
|
||||
self._reg_ending(result)
|
||||
|
@@ -8,12 +8,10 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import pyudev
|
||||
import threading
|
||||
from .refresh import event_add
|
||||
from . import cfg
|
||||
|
||||
observer = None
|
||||
observer_lock = threading.RLock()
|
||||
|
||||
|
||||
# noinspection PyUnusedLocal
|
||||
@@ -42,20 +40,15 @@ def filter_event(action, device):
|
||||
|
||||
|
||||
def add():
|
||||
with observer_lock:
|
||||
global observer
|
||||
context = pyudev.Context()
|
||||
monitor = pyudev.Monitor.from_netlink(context)
|
||||
monitor.filter_by('block')
|
||||
observer = pyudev.MonitorObserver(monitor, filter_event)
|
||||
observer.start()
|
||||
global observer
|
||||
context = pyudev.Context()
|
||||
monitor = pyudev.Monitor.from_netlink(context)
|
||||
monitor.filter_by('block')
|
||||
observer = pyudev.MonitorObserver(monitor, filter_event)
|
||||
observer.start()
|
||||
|
||||
|
||||
def remove():
|
||||
with observer_lock:
|
||||
global observer
|
||||
if observer:
|
||||
observer.stop()
|
||||
observer = None
|
||||
return True
|
||||
return False
|
||||
global observer
|
||||
observer.stop()
|
||||
observer = None
|
||||
|
@@ -13,11 +13,15 @@ import inspect
|
||||
import ctypes
|
||||
import os
|
||||
import string
|
||||
import datetime
|
||||
|
||||
import dbus
|
||||
from lvmdbusd import cfg
|
||||
import dbus.service
|
||||
import dbus.mainloop.glib
|
||||
|
||||
try:
|
||||
from . import cfg
|
||||
except SystemError:
|
||||
import cfg
|
||||
|
||||
STDOUT_TTY = os.isatty(sys.stdout.fileno())
|
||||
|
||||
@@ -145,27 +149,17 @@ def add_properties(xml, interface, props):
|
||||
:param props: Output from get_properties
|
||||
:return: updated XML string
|
||||
"""
|
||||
root = Et.fromstring(xml)
|
||||
|
||||
if props:
|
||||
root = Et.fromstring(xml)
|
||||
interface_element = None
|
||||
|
||||
# Check to see if interface is present
|
||||
for c in root:
|
||||
# print c.attrib['name']
|
||||
if c.attrib['name'] == interface:
|
||||
interface_element = c
|
||||
break
|
||||
|
||||
# Interface is not present, lets create it so we have something to
|
||||
# attach the properties too
|
||||
if interface_element is None:
|
||||
interface_element = Et.Element("interface", name=interface)
|
||||
root.append(interface_element)
|
||||
|
||||
# Add the properties
|
||||
for p in props:
|
||||
temp = '<property type="%s" name="%s" access="%s"/>\n' % \
|
||||
(p['p_t'], p['p_name'], p['p_access'])
|
||||
interface_element.append(Et.fromstring(temp))
|
||||
for p in props:
|
||||
temp = '<property type="%s" name="%s" access="%s"/>\n' % \
|
||||
(p['p_t'], p['p_name'], p['p_access'])
|
||||
c.append(Et.fromstring(temp))
|
||||
|
||||
return Et.tostring(root, encoding='utf8')
|
||||
return xml
|
||||
@@ -241,7 +235,7 @@ def parse_tags(tags):
|
||||
if len(tags):
|
||||
if ',' in tags:
|
||||
return tags.split(',')
|
||||
return dbus.Array(sorted([tags]), signature='s')
|
||||
return sorted([tags])
|
||||
return dbus.Array([], signature='s')
|
||||
|
||||
|
||||
@@ -249,13 +243,7 @@ def _common_log(msg, *attributes):
|
||||
cfg.stdout_lock.acquire()
|
||||
tid = ctypes.CDLL('libc.so.6').syscall(186)
|
||||
|
||||
if STDOUT_TTY:
|
||||
msg = "%s: %d:%d - %s" % \
|
||||
(datetime.datetime.now().strftime("%b %d %H:%M:%S.%f"),
|
||||
os.getpid(), tid, msg)
|
||||
|
||||
else:
|
||||
msg = "%d:%d - %s" % (os.getpid(), tid, msg)
|
||||
msg = "%d:%d - %s" % (os.getpid(), tid, msg)
|
||||
|
||||
if STDOUT_TTY and attributes:
|
||||
print(color(msg, *attributes))
|
||||
@@ -270,7 +258,7 @@ def _common_log(msg, *attributes):
|
||||
# @param msg Message to output to stdout
|
||||
# @return None
|
||||
def log_debug(msg, *attributes):
|
||||
if cfg.args and cfg.args.debug:
|
||||
if cfg.DEBUG:
|
||||
_common_log(msg, *attributes)
|
||||
|
||||
|
||||
@@ -401,7 +389,7 @@ def round_size(size_bytes):
|
||||
return size_bytes + bs - remainder
|
||||
|
||||
|
||||
_ALLOWABLE_CH = string.ascii_letters + string.digits + '#+-.:=@_\/%'
|
||||
_ALLOWABLE_CH = string.ascii_letters + string.digits + '#+.:=@_\/%'
|
||||
_ALLOWABLE_CH_SET = set(_ALLOWABLE_CH)
|
||||
|
||||
_ALLOWABLE_VG_LV_CH = string.ascii_letters + string.digits + '.-_+'
|
||||
|
@@ -20,7 +20,6 @@ from .loader import common
|
||||
from .state import State
|
||||
from . import background
|
||||
from .utils import round_size
|
||||
from .job import JobState
|
||||
|
||||
|
||||
# noinspection PyUnusedLocal
|
||||
@@ -67,7 +66,7 @@ class VgState(State):
|
||||
|
||||
gen = utils.lv_object_path_method(lv_name, meta)
|
||||
|
||||
lv_path = cfg.om.get_object_path_by_uuid_lvm_id(
|
||||
lv_path = cfg.om.get_object_path_by_lvm_id(
|
||||
lv_uuid, full_name, gen)
|
||||
rc.append(lv_path)
|
||||
return dbus.Array(rc, signature='o')
|
||||
@@ -76,9 +75,9 @@ class VgState(State):
|
||||
rc = []
|
||||
for p in cfg.db.pvs_in_vg(self.Uuid):
|
||||
(pv_name, pv_uuid) = p
|
||||
rc.append(cfg.om.get_object_path_by_uuid_lvm_id(
|
||||
rc.append(cfg.om.get_object_path_by_lvm_id(
|
||||
pv_uuid, pv_name, pv_obj_path_generate))
|
||||
return rc
|
||||
return dbus.Array(rc, signature='o')
|
||||
|
||||
def __init__(self, Uuid, Name, Fmt,
|
||||
SizeBytes, FreeBytes, SysId, ExtentSizeBytes,
|
||||
@@ -91,7 +90,7 @@ class VgState(State):
|
||||
|
||||
def create_dbus_object(self, path):
|
||||
if not path:
|
||||
path = cfg.om.get_object_path_by_uuid_lvm_id(
|
||||
path = cfg.om.get_object_path_by_lvm_id(
|
||||
self.Uuid, self.Name, vg_obj_path_generate)
|
||||
return Vg(path, self)
|
||||
|
||||
@@ -145,8 +144,13 @@ class Vg(AutomatedProperties):
|
||||
|
||||
@staticmethod
|
||||
def fetch_new_lv(vg_name, lv_name):
|
||||
full_name = "%s/%s" % (vg_name, lv_name)
|
||||
|
||||
cfg.load()
|
||||
return cfg.om.get_object_path_by_lvm_id("%s/%s" % (vg_name, lv_name))
|
||||
l = cfg.om.get_object_by_lvm_id(full_name)
|
||||
created_lv = l.dbus_object_path()
|
||||
|
||||
return created_lv
|
||||
|
||||
@staticmethod
|
||||
def _rename(uuid, vg_name, new_name, rename_options):
|
||||
@@ -233,7 +237,10 @@ class Vg(AutomatedProperties):
|
||||
# locals(), ['Variant']).Variant("s", "n")}
|
||||
|
||||
if rc == 0:
|
||||
cfg.load()
|
||||
dbo.refresh()
|
||||
|
||||
if (('activate' in change_options) or ('-a' in change_options)):
|
||||
cfg.load()
|
||||
else:
|
||||
raise dbus.exceptions.DBusException(
|
||||
VG_INTERFACE,
|
||||
@@ -353,20 +360,12 @@ class Vg(AutomatedProperties):
|
||||
@dbus.service.method(
|
||||
dbus_interface=VG_INTERFACE,
|
||||
in_signature='o(tt)a(ott)ia{sv}',
|
||||
out_signature='o',
|
||||
async_callbacks=('cb', 'cbe'))
|
||||
out_signature='o')
|
||||
def Move(self, pv_src_obj, pv_source_range, pv_dests_and_ranges,
|
||||
tmo, move_options, cb, cbe):
|
||||
|
||||
job_state = JobState()
|
||||
|
||||
r = RequestEntry(
|
||||
tmo, background.move,
|
||||
(VG_INTERFACE, None, pv_src_obj, pv_source_range,
|
||||
pv_dests_and_ranges, move_options, job_state), cb, cbe, False,
|
||||
job_state)
|
||||
|
||||
cfg.worker_q.put(r)
|
||||
tmo, move_options):
|
||||
return background.move(
|
||||
VG_INTERFACE, None, pv_src_obj, pv_source_range,
|
||||
pv_dests_and_ranges, move_options, tmo)
|
||||
|
||||
@staticmethod
|
||||
def _lv_create(uuid, vg_name, name, size_bytes, pv_dests_and_ranges,
|
||||
@@ -840,7 +839,9 @@ class Vg(AutomatedProperties):
|
||||
cfg.worker_q.put(r)
|
||||
|
||||
def _attribute(self, pos, ch):
|
||||
return dbus.Boolean(self.state.attr[pos] == ch)
|
||||
if self.state.attr[pos] == ch:
|
||||
return True
|
||||
return False
|
||||
|
||||
@dbus.service.method(
|
||||
dbus_interface=VG_INTERFACE,
|
||||
@@ -906,11 +907,11 @@ class Vg(AutomatedProperties):
|
||||
|
||||
@property
|
||||
def Pvs(self):
|
||||
return dbus.Array(self.state.Pvs, signature='o')
|
||||
return self.state.Pvs
|
||||
|
||||
@property
|
||||
def Lvs(self):
|
||||
return dbus.Array(self.state.Lvs, signature='o')
|
||||
return self.state.Lvs
|
||||
|
||||
@property
|
||||
def lvm_id(self):
|
||||
|
@@ -37,12 +37,11 @@ int main(int argc, char **argv)
|
||||
printf("lvmetactl dump\n");
|
||||
printf("lvmetactl pv_list\n");
|
||||
printf("lvmetactl vg_list\n");
|
||||
printf("lvmetactl get_global_info\n");
|
||||
printf("lvmetactl vg_lookup_name <name>\n");
|
||||
printf("lvmetactl vg_lookup_uuid <uuid>\n");
|
||||
printf("lvmetactl pv_lookup_uuid <uuid>\n");
|
||||
printf("lvmetactl set_global_invalid 0|1\n");
|
||||
printf("lvmetactl set_global_disable 0|1\n");
|
||||
printf("lvmetactl get_global_invalid\n");
|
||||
printf("lvmetactl set_vg_version <uuid> <name> <version>\n");
|
||||
printf("lvmetactl vg_lock_type <uuid>\n");
|
||||
return -1;
|
||||
@@ -55,32 +54,18 @@ int main(int argc, char **argv)
|
||||
if (!strcmp(cmd, "dump")) {
|
||||
reply = daemon_send_simple(h, "dump",
|
||||
"token = %s", "skip",
|
||||
"pid = " FMTd64, (int64_t)getpid(),
|
||||
"cmd = %s", "lvmetactl",
|
||||
NULL);
|
||||
printf("%s\n", reply.buffer.mem);
|
||||
|
||||
} else if (!strcmp(cmd, "pv_list")) {
|
||||
reply = daemon_send_simple(h, "pv_list",
|
||||
"token = %s", "skip",
|
||||
"pid = " FMTd64, (int64_t)getpid(),
|
||||
"cmd = %s", "lvmetactl",
|
||||
NULL);
|
||||
printf("%s\n", reply.buffer.mem);
|
||||
|
||||
} else if (!strcmp(cmd, "vg_list")) {
|
||||
reply = daemon_send_simple(h, "vg_list",
|
||||
"token = %s", "skip",
|
||||
"pid = " FMTd64, (int64_t)getpid(),
|
||||
"cmd = %s", "lvmetactl",
|
||||
NULL);
|
||||
printf("%s\n", reply.buffer.mem);
|
||||
|
||||
} else if (!strcmp(cmd, "get_global_info")) {
|
||||
reply = daemon_send_simple(h, "get_global_info",
|
||||
"token = %s", "skip",
|
||||
"pid = " FMTd64, (int64_t)getpid(),
|
||||
"cmd = %s", "lvmetactl",
|
||||
NULL);
|
||||
printf("%s\n", reply.buffer.mem);
|
||||
|
||||
@@ -94,26 +79,14 @@ int main(int argc, char **argv)
|
||||
reply = daemon_send_simple(h, "set_global_info",
|
||||
"global_invalid = " FMTd64, (int64_t) val,
|
||||
"token = %s", "skip",
|
||||
"pid = " FMTd64, (int64_t)getpid(),
|
||||
"cmd = %s", "lvmetactl",
|
||||
NULL);
|
||||
print_reply(reply);
|
||||
|
||||
} else if (!strcmp(cmd, "set_global_disable")) {
|
||||
if (argc < 3) {
|
||||
printf("set_global_disable 0|1\n");
|
||||
return -1;
|
||||
}
|
||||
val = atoi(argv[2]);
|
||||
|
||||
reply = daemon_send_simple(h, "set_global_info",
|
||||
"global_disable = " FMTd64, (int64_t) val,
|
||||
"disable_reason = %s", LVMETAD_DISABLE_REASON_DIRECT,
|
||||
} else if (!strcmp(cmd, "get_global_invalid")) {
|
||||
reply = daemon_send_simple(h, "get_global_info",
|
||||
"token = %s", "skip",
|
||||
"pid = " FMTd64, (int64_t)getpid(),
|
||||
"cmd = %s", "lvmetactl",
|
||||
NULL);
|
||||
print_reply(reply);
|
||||
printf("%s\n", reply.buffer.mem);
|
||||
|
||||
} else if (!strcmp(cmd, "set_vg_version")) {
|
||||
if (argc < 5) {
|
||||
@@ -135,24 +108,18 @@ int main(int argc, char **argv)
|
||||
"name = %s", name,
|
||||
"version = " FMTd64, (int64_t) ver,
|
||||
"token = %s", "skip",
|
||||
"pid = " FMTd64, (int64_t)getpid(),
|
||||
"cmd = %s", "lvmetactl",
|
||||
NULL);
|
||||
} else if (uuid) {
|
||||
reply = daemon_send_simple(h, "set_vg_info",
|
||||
"uuid = %s", uuid,
|
||||
"version = " FMTd64, (int64_t) ver,
|
||||
"token = %s", "skip",
|
||||
"pid = " FMTd64, (int64_t)getpid(),
|
||||
"cmd = %s", "lvmetactl",
|
||||
NULL);
|
||||
} else if (name) {
|
||||
reply = daemon_send_simple(h, "set_vg_info",
|
||||
"name = %s", name,
|
||||
"version = " FMTd64, (int64_t) ver,
|
||||
"token = %s", "skip",
|
||||
"pid = " FMTd64, (int64_t)getpid(),
|
||||
"cmd = %s", "lvmetactl",
|
||||
NULL);
|
||||
} else {
|
||||
printf("name or uuid required\n");
|
||||
@@ -171,8 +138,6 @@ int main(int argc, char **argv)
|
||||
reply = daemon_send_simple(h, "vg_lookup",
|
||||
"name = %s", name,
|
||||
"token = %s", "skip",
|
||||
"pid = " FMTd64, (int64_t)getpid(),
|
||||
"cmd = %s", "lvmetactl",
|
||||
NULL);
|
||||
printf("%s\n", reply.buffer.mem);
|
||||
|
||||
@@ -186,8 +151,6 @@ int main(int argc, char **argv)
|
||||
reply = daemon_send_simple(h, "vg_lookup",
|
||||
"uuid = %s", uuid,
|
||||
"token = %s", "skip",
|
||||
"pid = " FMTd64, (int64_t)getpid(),
|
||||
"cmd = %s", "lvmetactl",
|
||||
NULL);
|
||||
printf("%s\n", reply.buffer.mem);
|
||||
|
||||
@@ -204,8 +167,6 @@ int main(int argc, char **argv)
|
||||
reply = daemon_send_simple(h, "vg_lookup",
|
||||
"uuid = %s", uuid,
|
||||
"token = %s", "skip",
|
||||
"pid = " FMTd64, (int64_t)getpid(),
|
||||
"cmd = %s", "lvmetactl",
|
||||
NULL);
|
||||
/* printf("%s\n", reply.buffer.mem); */
|
||||
|
||||
@@ -232,8 +193,6 @@ int main(int argc, char **argv)
|
||||
reply = daemon_send_simple(h, "pv_lookup",
|
||||
"uuid = %s", uuid,
|
||||
"token = %s", "skip",
|
||||
"pid = " FMTd64, (int64_t)getpid(),
|
||||
"cmd = %s", "lvmetactl",
|
||||
NULL);
|
||||
printf("%s\n", reply.buffer.mem);
|
||||
|
||||
|
@@ -19,13 +19,6 @@
|
||||
|
||||
#define LVMETAD_SOCKET DEFAULT_RUN_DIR "/lvmetad.socket"
|
||||
|
||||
#define LVMETAD_TOKEN_UPDATE_IN_PROGRESS "update in progress"
|
||||
|
||||
#define LVMETAD_DISABLE_REASON_DIRECT "DIRECT"
|
||||
#define LVMETAD_DISABLE_REASON_LVM1 "LVM1"
|
||||
#define LVMETAD_DISABLE_REASON_DUPLICATES "DUPLICATES"
|
||||
#define LVMETAD_DISABLE_REASON_VGRESTORE "VGRESTORE"
|
||||
|
||||
struct volume_group;
|
||||
|
||||
/* Different types of replies we may get from lvmetad. */
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -75,10 +75,7 @@ int scan(daemon_handle h, char *fn) {
|
||||
}
|
||||
|
||||
char uuid[64];
|
||||
if (!id_write_format(dev->pvid, uuid, 64)) {
|
||||
fprintf(stderr, "[C] Failed to format PV UUID for %s", dev_name(dev));
|
||||
return;
|
||||
}
|
||||
id_write_format(dev->pvid, uuid, 64);
|
||||
fprintf(stderr, "[C] found PV: %s\n", uuid);
|
||||
struct lvmcache_info *info = (struct lvmcache_info *) label->info;
|
||||
struct physical_volume pv = { 0, };
|
||||
|
@@ -77,7 +77,7 @@ static void save_client_info(char *line)
|
||||
uint32_t client_id = 0;
|
||||
char name[MAX_NAME+1] = { 0 };
|
||||
|
||||
(void) sscanf(line, "info=client pid=%u fd=%d pi=%d id=%u name=%s",
|
||||
sscanf(line, "info=client pid=%u fd=%d pi=%d id=%u name=%s",
|
||||
&pid, &fd, &pi, &client_id, name);
|
||||
|
||||
clients[num_clients].client_id = client_id;
|
||||
@@ -110,7 +110,7 @@ static void format_info_ls(char *line)
|
||||
char lock_args[MAX_ARGS+1] = { 0 };
|
||||
char lock_type[MAX_NAME+1] = { 0 };
|
||||
|
||||
(void) sscanf(line, "info=ls ls_name=%s vg_name=%s vg_uuid=%s vg_sysid=%s vg_args=%s lm_type=%s",
|
||||
sscanf(line, "info=ls ls_name=%s vg_name=%s vg_uuid=%s vg_sysid=%s vg_args=%s lm_type=%s",
|
||||
ls_name, vg_name, vg_uuid, vg_sysid, lock_args, lock_type);
|
||||
|
||||
if (!first_ls)
|
||||
@@ -131,7 +131,7 @@ static void format_info_ls_action(char *line)
|
||||
uint32_t pid = 0;
|
||||
char cl_name[MAX_NAME+1] = { 0 };
|
||||
|
||||
(void) sscanf(line, "info=ls_action client_id=%u %s %s op=%s",
|
||||
sscanf(line, "info=ls_action client_id=%u %s %s op=%s",
|
||||
&client_id, flags, version, op);
|
||||
|
||||
find_client_info(client_id, &pid, cl_name);
|
||||
@@ -147,7 +147,7 @@ static void format_info_r(char *line, char *r_name_out, char *r_type_out)
|
||||
char sh_count[MAX_NAME+1] = { 0 };
|
||||
uint32_t ver = 0;
|
||||
|
||||
(void) sscanf(line, "info=r name=%s type=%s mode=%s %s version=%u",
|
||||
sscanf(line, "info=r name=%s type=%s mode=%s %s version=%u",
|
||||
r_name, r_type, mode, sh_count, &ver);
|
||||
|
||||
strcpy(r_name_out, r_name);
|
||||
@@ -185,7 +185,7 @@ static void format_info_lk(char *line, char *r_name, char *r_type)
|
||||
return;
|
||||
}
|
||||
|
||||
(void) sscanf(line, "info=lk mode=%s version=%u %s client_id=%u",
|
||||
sscanf(line, "info=lk mode=%s version=%u %s client_id=%u",
|
||||
mode, &ver, flags, &client_id);
|
||||
|
||||
find_client_info(client_id, &pid, cl_name);
|
||||
@@ -221,7 +221,7 @@ static void format_info_r_action(char *line, char *r_name, char *r_type)
|
||||
return;
|
||||
}
|
||||
|
||||
(void) sscanf(line, "info=r_action client_id=%u %s %s op=%s rt=%s mode=%s %s %s %s",
|
||||
sscanf(line, "info=r_action client_id=%u %s %s op=%s rt=%s mode=%s %s %s %s",
|
||||
&client_id, flags, version, op, rt, mode, lm, result, lm_rv);
|
||||
|
||||
find_client_info(client_id, &pid, cl_name);
|
||||
|
@@ -306,13 +306,7 @@ static const char *_syslog_num_to_name(int num)
|
||||
static uint64_t monotime(void)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &ts)) {
|
||||
log_error("clock_gettime failed to get timestamp %s.",
|
||||
strerror(errno));
|
||||
ts.tv_sec = 0;
|
||||
}
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return ts.tv_sec;
|
||||
}
|
||||
|
||||
@@ -323,7 +317,7 @@ static void log_save_line(int len, char *line,
|
||||
unsigned int w = *wrap;
|
||||
int i;
|
||||
|
||||
if (len < (int) (LOG_DUMP_SIZE - p)) {
|
||||
if (len < LOG_DUMP_SIZE - p) {
|
||||
memcpy(log_buf + p, line, len);
|
||||
p += len;
|
||||
|
||||
@@ -1013,7 +1007,6 @@ static daemon_reply send_lvmetad(const char *id, ...)
|
||||
daemon_reply reply;
|
||||
va_list ap;
|
||||
int retries = 0;
|
||||
int err;
|
||||
|
||||
va_start(ap, id);
|
||||
|
||||
@@ -1023,28 +1016,20 @@ static daemon_reply send_lvmetad(const char *id, ...)
|
||||
*/
|
||||
pthread_mutex_lock(&lvmetad_mutex);
|
||||
retry:
|
||||
if (!lvmetad_connected) {
|
||||
lvmetad_handle = lvmetad_open(NULL);
|
||||
if (lvmetad_handle.error || lvmetad_handle.socket_fd < 0) {
|
||||
err = lvmetad_handle.error ?: lvmetad_handle.socket_fd;
|
||||
pthread_mutex_unlock(&lvmetad_mutex);
|
||||
log_error("lvmetad_open reconnect error %d", err);
|
||||
memset(&reply, 0, sizeof(reply));
|
||||
reply.error = err;
|
||||
va_end(ap);
|
||||
return reply;
|
||||
} else {
|
||||
log_debug("lvmetad reconnected");
|
||||
lvmetad_connected = 1;
|
||||
}
|
||||
}
|
||||
|
||||
reply = daemon_send_simple_v(lvmetad_handle, id, ap);
|
||||
|
||||
/* lvmetad may have been restarted */
|
||||
if ((reply.error == ECONNRESET) && (retries < 2)) {
|
||||
daemon_close(lvmetad_handle);
|
||||
lvmetad_connected = 0;
|
||||
|
||||
lvmetad_handle = lvmetad_open(NULL);
|
||||
if (lvmetad_handle.error || lvmetad_handle.socket_fd < 0) {
|
||||
log_error("lvmetad_open reconnect error %d", lvmetad_handle.error);
|
||||
} else {
|
||||
log_debug("lvmetad reconnected");
|
||||
lvmetad_connected = 1;
|
||||
}
|
||||
retries++;
|
||||
goto retry;
|
||||
}
|
||||
@@ -1249,6 +1234,10 @@ static int res_lock(struct lockspace *ls, struct resource *r, struct action *act
|
||||
rv = -EREMOVED;
|
||||
}
|
||||
|
||||
if (!lvmetad_connected && inval_meta)
|
||||
log_debug("S %s R %s res_lock no lvmetad connection to invalidate",
|
||||
ls->name, r->name);
|
||||
|
||||
/*
|
||||
* r is vglk: tell lvmetad to set the vg invalid
|
||||
* flag, and provide the new r_version. If lvmetad finds
|
||||
@@ -1264,7 +1253,7 @@ static int res_lock(struct lockspace *ls, struct resource *r, struct action *act
|
||||
* caches, and tell lvmetad to set global invalid to 0.
|
||||
*/
|
||||
|
||||
if (inval_meta && (r->type == LD_RT_VG)) {
|
||||
if (lvmetad_connected && inval_meta && (r->type == LD_RT_VG)) {
|
||||
daemon_reply reply;
|
||||
char *uuid;
|
||||
|
||||
@@ -1288,7 +1277,7 @@ static int res_lock(struct lockspace *ls, struct resource *r, struct action *act
|
||||
daemon_reply_destroy(reply);
|
||||
}
|
||||
|
||||
if (inval_meta && (r->type == LD_RT_GL)) {
|
||||
if (lvmetad_connected && inval_meta && (r->type == LD_RT_GL)) {
|
||||
daemon_reply reply;
|
||||
|
||||
log_debug("S %s R %s res_lock set lvmetad global invalid",
|
||||
@@ -1654,9 +1643,6 @@ static int res_able(struct lockspace *ls, struct resource *r,
|
||||
}
|
||||
|
||||
rv = lm_able_gl_sanlock(ls, act->op == LD_OP_ENABLE);
|
||||
|
||||
if (!rv && (act->op == LD_OP_ENABLE))
|
||||
gl_vg_removed = 0;
|
||||
out:
|
||||
return rv;
|
||||
}
|
||||
@@ -2283,7 +2269,6 @@ static void *lockspace_thread_main(void *arg_in)
|
||||
struct action *act_op_free = NULL;
|
||||
struct list_head tmp_act;
|
||||
struct list_head act_close;
|
||||
char tmp_name[MAX_NAME+1];
|
||||
int free_vg = 0;
|
||||
int drop_vg = 0;
|
||||
int error = 0;
|
||||
@@ -2630,10 +2615,8 @@ out_act:
|
||||
|
||||
if (free_vg && ls->sanlock_gl_enabled && act_op_free) {
|
||||
pthread_mutex_lock(&lockspaces_mutex);
|
||||
if (other_sanlock_vgs_exist(ls)) {
|
||||
if (other_sanlock_vgs_exist(ls))
|
||||
act_op_free->flags |= LD_AF_WARN_GL_REMOVED;
|
||||
gl_vg_removed = 1;
|
||||
}
|
||||
pthread_mutex_unlock(&lockspaces_mutex);
|
||||
}
|
||||
|
||||
@@ -2651,10 +2634,6 @@ out_act:
|
||||
ls->drop_vg = drop_vg;
|
||||
if (ls->lm_type == LD_LM_DLM && !strcmp(ls->name, gl_lsname_dlm))
|
||||
global_dlm_lockspace_exists = 0;
|
||||
/* Avoid a name collision of the same lockspace is added again before this thread is cleaned up. */
|
||||
memset(tmp_name, 0, sizeof(tmp_name));
|
||||
snprintf(tmp_name, MAX_NAME, "REM:%s", ls->name);
|
||||
memcpy(ls->name, tmp_name, MAX_NAME);
|
||||
pthread_mutex_unlock(&lockspaces_mutex);
|
||||
|
||||
/* worker_thread will join this thread, and free the ls */
|
||||
@@ -3134,8 +3113,6 @@ static int for_each_lockspace(int do_stop, int do_free, int do_force)
|
||||
|
||||
/* FIXME: will free_vg ever not be set? */
|
||||
|
||||
log_debug("free ls %s", ls->name);
|
||||
|
||||
if (ls->free_vg) {
|
||||
/* In future we may need to free ls->actions here */
|
||||
free_ls_resources(ls);
|
||||
@@ -3356,10 +3333,7 @@ static void *worker_thread_main(void *arg_in)
|
||||
|
||||
while (1) {
|
||||
pthread_mutex_lock(&worker_mutex);
|
||||
if (clock_gettime(CLOCK_REALTIME, &ts)) {
|
||||
log_error("clock_gettime failed.");
|
||||
ts.tv_sec = ts.tv_nsec = 0;
|
||||
}
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
ts.tv_sec += delay_sec;
|
||||
rv = 0;
|
||||
act = NULL;
|
||||
@@ -3391,11 +3365,6 @@ static void *worker_thread_main(void *arg_in)
|
||||
int run_sanlock = lm_is_running_sanlock();
|
||||
int run_dlm = lm_is_running_dlm();
|
||||
|
||||
if (daemon_test) {
|
||||
run_sanlock = gl_use_sanlock;
|
||||
run_dlm = gl_use_dlm;
|
||||
}
|
||||
|
||||
if (run_sanlock && run_dlm)
|
||||
act->result = -EXFULL;
|
||||
else if (!run_sanlock && !run_dlm)
|
||||
@@ -3673,7 +3642,7 @@ static int client_send_result(struct client *cl, struct action *act)
|
||||
if (act->flags & LD_AF_DUP_GL_LS)
|
||||
strcat(result_flags, "DUP_GL_LS,");
|
||||
|
||||
if ((act->flags & LD_AF_WARN_GL_REMOVED) || gl_vg_removed)
|
||||
if (act->flags & LD_AF_WARN_GL_REMOVED)
|
||||
strcat(result_flags, "WARN_GL_REMOVED,");
|
||||
|
||||
if (act->op == LD_OP_INIT) {
|
||||
@@ -4431,7 +4400,7 @@ static void client_recv_action(struct client *cl)
|
||||
return;
|
||||
}
|
||||
|
||||
req.cft = config_tree_from_string_without_dup_node_check(req.buffer.mem);
|
||||
req.cft = dm_config_from_string(req.buffer.mem);
|
||||
if (!req.cft) {
|
||||
log_error("client recv %u config_from_string error", cl->id);
|
||||
buffer_destroy(&req.buffer);
|
||||
|
@@ -320,7 +320,6 @@ static inline int list_empty(const struct list_head *head)
|
||||
EXTERN int gl_type_static;
|
||||
EXTERN int gl_use_dlm;
|
||||
EXTERN int gl_use_sanlock;
|
||||
EXTERN int gl_vg_removed;
|
||||
EXTERN char gl_lsname_dlm[MAX_NAME+1];
|
||||
EXTERN char gl_lsname_sanlock[MAX_NAME+1];
|
||||
EXTERN int global_dlm_lockspace_exists;
|
||||
|
@@ -206,7 +206,7 @@ int lm_data_size_sanlock(void)
|
||||
#define VG_LOCK_BEGIN UINT64_C(66)
|
||||
#define LV_LOCK_BEGIN UINT64_C(67)
|
||||
|
||||
static uint64_t daemon_test_lv_count;
|
||||
static unsigned int daemon_test_lv_count;
|
||||
|
||||
static int lock_lv_name_from_args(char *vg_args, char *lock_lv_name)
|
||||
{
|
||||
@@ -276,8 +276,8 @@ static int read_host_id_file(void)
|
||||
*sep = '\0';
|
||||
memset(key_str, 0, sizeof(key_str));
|
||||
memset(val_str, 0, sizeof(val_str));
|
||||
(void) sscanf(key, "%s", key_str);
|
||||
(void) sscanf(val, "%s", val_str);
|
||||
sscanf(key, "%s", key_str);
|
||||
sscanf(val, "%s", val_str);
|
||||
|
||||
if (!strcmp(key_str, "host_id")) {
|
||||
host_id = atoi(val_str);
|
||||
@@ -1416,12 +1416,14 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
if (adopt)
|
||||
flags |= SANLK_ACQUIRE_ORPHAN_ONLY;
|
||||
|
||||
#ifdef SANLOCK_HAS_ACQUIRE_OWNER_NOWAIT
|
||||
/*
|
||||
* Don't block waiting for a failed lease to expire since it causes
|
||||
* sanlock_acquire to block for a long time, which would prevent this
|
||||
* thread from processing other lock requests.
|
||||
*/
|
||||
flags |= SANLK_ACQUIRE_OWNER_NOWAIT;
|
||||
#endif
|
||||
|
||||
memset(&opt, 0, sizeof(opt));
|
||||
sprintf(opt.owner_name, "%s", "lvmlockd");
|
||||
@@ -1496,6 +1498,7 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
#ifdef SANLOCK_HAS_ACQUIRE_OWNER_NOWAIT
|
||||
if (rv == SANLK_ACQUIRE_OWNED_RETRY) {
|
||||
/*
|
||||
* The lock is held by a failed host, and will eventually
|
||||
@@ -1514,7 +1517,7 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
*retry = 0;
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
#endif
|
||||
if (rv < 0) {
|
||||
log_error("S %s R %s lock_san acquire error %d",
|
||||
ls->name, r->name, rv);
|
||||
|
@@ -31,7 +31,7 @@ const char *polling_op(enum poll_type type)
|
||||
|
||||
static int add_to_cmd_arr(const char ***cmdargv, const char *str, unsigned *ind)
|
||||
{
|
||||
const char **newargv;
|
||||
const char **newargv = *cmdargv;
|
||||
|
||||
if (*ind && !(*ind % MIN_ARGV_SIZE)) {
|
||||
newargv = dm_realloc(*cmdargv, (*ind / MIN_ARGV_SIZE + 1) * MIN_ARGV_SIZE * sizeof(char *));
|
||||
|
@@ -11,7 +11,7 @@ Every bio that is mapped by the target is referred to the policy.
|
||||
The policy can return a simple HIT or MISS or issue a migration.
|
||||
|
||||
Currently there's no way for the policy to issue background work,
|
||||
e.g. to start writing back dirty blocks that are going to be evicted
|
||||
e.g. to start writing back dirty blocks that are going to be evicte
|
||||
soon.
|
||||
|
||||
Because we map bios, rather than requests it's easy for the policy
|
||||
@@ -25,77 +25,53 @@ trying to see when the io scheduler has let the ios run.
|
||||
Overview of supplied cache replacement policies
|
||||
===============================================
|
||||
|
||||
multiqueue (mq)
|
||||
---------------
|
||||
multiqueue
|
||||
----------
|
||||
|
||||
This policy is now an alias for smq (see below).
|
||||
This policy is the default.
|
||||
|
||||
The following tunables are accepted, but have no effect:
|
||||
The multiqueue policy has three sets of 16 queues: one set for entries
|
||||
waiting for the cache and another two for those in the cache (a set for
|
||||
clean entries and a set for dirty entries).
|
||||
|
||||
Cache entries in the queues are aged based on logical time. Entry into
|
||||
the cache is based on variable thresholds and queue selection is based
|
||||
on hit count on entry. The policy aims to take different cache miss
|
||||
costs into account and to adjust to varying load patterns automatically.
|
||||
|
||||
Message and constructor argument pairs are:
|
||||
'sequential_threshold <#nr_sequential_ios>'
|
||||
'random_threshold <#nr_random_ios>'
|
||||
'read_promote_adjustment <value>'
|
||||
'write_promote_adjustment <value>'
|
||||
'discard_promote_adjustment <value>'
|
||||
|
||||
Stochastic multiqueue (smq)
|
||||
---------------------------
|
||||
The sequential threshold indicates the number of contiguous I/Os
|
||||
required before a stream is treated as sequential. Once a stream is
|
||||
considered sequential it will bypass the cache. The random threshold
|
||||
is the number of intervening non-contiguous I/Os that must be seen
|
||||
before the stream is treated as random again.
|
||||
|
||||
This policy is the default.
|
||||
The sequential and random thresholds default to 512 and 4 respectively.
|
||||
|
||||
The stochastic multi-queue (smq) policy addresses some of the problems
|
||||
with the multiqueue (mq) policy.
|
||||
Large, sequential I/Os are probably better left on the origin device
|
||||
since spindles tend to have good sequential I/O bandwidth. The
|
||||
io_tracker counts contiguous I/Os to try to spot when the I/O is in one
|
||||
of these sequential modes. But there are use-cases for wanting to
|
||||
promote sequential blocks to the cache (e.g. fast application startup).
|
||||
If sequential threshold is set to 0 the sequential I/O detection is
|
||||
disabled and sequential I/O will no longer implicitly bypass the cache.
|
||||
Setting the random threshold to 0 does _not_ disable the random I/O
|
||||
stream detection.
|
||||
|
||||
The smq policy (vs mq) offers the promise of less memory utilization,
|
||||
improved performance and increased adaptability in the face of changing
|
||||
workloads. smq also does not have any cumbersome tuning knobs.
|
||||
|
||||
Users may switch from "mq" to "smq" simply by appropriately reloading a
|
||||
DM table that is using the cache target. Doing so will cause all of the
|
||||
mq policy's hints to be dropped. Also, performance of the cache may
|
||||
degrade slightly until smq recalculates the origin device's hotspots
|
||||
that should be cached.
|
||||
|
||||
Memory usage:
|
||||
The mq policy used a lot of memory; 88 bytes per cache block on a 64
|
||||
bit machine.
|
||||
|
||||
smq uses 28bit indexes to implement it's data structures rather than
|
||||
pointers. It avoids storing an explicit hit count for each block. It
|
||||
has a 'hotspot' queue, rather than a pre-cache, which uses a quarter of
|
||||
the entries (each hotspot block covers a larger area than a single
|
||||
cache block).
|
||||
|
||||
All this means smq uses ~25bytes per cache block. Still a lot of
|
||||
memory, but a substantial improvement nontheless.
|
||||
|
||||
Level balancing:
|
||||
mq placed entries in different levels of the multiqueue structures
|
||||
based on their hit count (~ln(hit count)). This meant the bottom
|
||||
levels generally had the most entries, and the top ones had very
|
||||
few. Having unbalanced levels like this reduced the efficacy of the
|
||||
multiqueue.
|
||||
|
||||
smq does not maintain a hit count, instead it swaps hit entries with
|
||||
the least recently used entry from the level above. The overall
|
||||
ordering being a side effect of this stochastic process. With this
|
||||
scheme we can decide how many entries occupy each multiqueue level,
|
||||
resulting in better promotion/demotion decisions.
|
||||
|
||||
Adaptability:
|
||||
The mq policy maintained a hit count for each cache block. For a
|
||||
different block to get promoted to the cache it's hit count has to
|
||||
exceed the lowest currently in the cache. This meant it could take a
|
||||
long time for the cache to adapt between varying IO patterns.
|
||||
|
||||
smq doesn't maintain hit counts, so a lot of this problem just goes
|
||||
away. In addition it tracks performance of the hotspot queue, which
|
||||
is used to decide which blocks to promote. If the hotspot queue is
|
||||
performing badly then it starts moving entries more quickly between
|
||||
levels. This lets it adapt to new IO patterns very quickly.
|
||||
|
||||
Performance:
|
||||
Testing smq shows substantially better performance than mq.
|
||||
Internally the mq policy determines a promotion threshold. If the hit
|
||||
count of a block not in the cache goes above this threshold it gets
|
||||
promoted to the cache. The read, write and discard promote adjustment
|
||||
tunables allow you to tweak the promotion threshold by adding a small
|
||||
value based on the io type. They default to 4, 8 and 1 respectively.
|
||||
If you're trying to quickly warm a new cache device you may wish to
|
||||
reduce these to encourage promotion. Remember to switch them back to
|
||||
their defaults after the cache fills though.
|
||||
|
||||
cleaner
|
||||
-------
|
||||
|
@@ -221,7 +221,6 @@ Status
|
||||
<#read hits> <#read misses> <#write hits> <#write misses>
|
||||
<#demotions> <#promotions> <#dirty> <#features> <features>*
|
||||
<#core args> <core args>* <policy name> <#policy args> <policy args>*
|
||||
<cache metadata mode>
|
||||
|
||||
metadata block size : Fixed block size for each metadata block in
|
||||
sectors
|
||||
@@ -252,18 +251,8 @@ core args : Key/value pairs for tuning the core
|
||||
e.g. migration_threshold
|
||||
policy name : Name of the policy
|
||||
#policy args : Number of policy arguments to follow (must be even)
|
||||
policy args : Key/value pairs e.g. sequential_threshold
|
||||
cache metadata mode : ro if read-only, rw if read-write
|
||||
In serious cases where even a read-only mode is deemed unsafe
|
||||
no further I/O will be permitted and the status will just
|
||||
contain the string 'Fail'. The userspace recovery tools
|
||||
should then be used.
|
||||
needs_check : 'needs_check' if set, '-' if not set
|
||||
A metadata operation has failed, resulting in the needs_check
|
||||
flag being set in the metadata's superblock. The metadata
|
||||
device must be deactivated and checked/repaired before the
|
||||
cache can be made fully operational again. '-' indicates
|
||||
needs_check is not set.
|
||||
policy args : Key/value pairs
|
||||
e.g. sequential_threshold
|
||||
|
||||
Messages
|
||||
--------
|
||||
|
@@ -8,7 +8,6 @@ Parameters:
|
||||
<device> <offset> <delay> [<write_device> <write_offset> <write_delay>]
|
||||
|
||||
With separate write parameters, the first set is only used for reads.
|
||||
Offsets are specified in sectors.
|
||||
Delays are specified in milliseconds.
|
||||
|
||||
Example scripts
|
||||
|
@@ -209,37 +209,6 @@ include:
|
||||
"repair" - Initiate a repair of the array.
|
||||
"reshape"- Currently unsupported (-EINVAL).
|
||||
|
||||
|
||||
Discard Support
|
||||
---------------
|
||||
The implementation of discard support among hardware vendors varies.
|
||||
When a block is discarded, some storage devices will return zeroes when
|
||||
the block is read. These devices set the 'discard_zeroes_data'
|
||||
attribute. Other devices will return random data. Confusingly, some
|
||||
devices that advertise 'discard_zeroes_data' will not reliably return
|
||||
zeroes when discarded blocks are read! Since RAID 4/5/6 uses blocks
|
||||
from a number of devices to calculate parity blocks and (for performance
|
||||
reasons) relies on 'discard_zeroes_data' being reliable, it is important
|
||||
that the devices be consistent. Blocks may be discarded in the middle
|
||||
of a RAID 4/5/6 stripe and if subsequent read results are not
|
||||
consistent, the parity blocks may be calculated differently at any time;
|
||||
making the parity blocks useless for redundancy. It is important to
|
||||
understand how your hardware behaves with discards if you are going to
|
||||
enable discards with RAID 4/5/6.
|
||||
|
||||
Since the behavior of storage devices is unreliable in this respect,
|
||||
even when reporting 'discard_zeroes_data', by default RAID 4/5/6
|
||||
discard support is disabled -- this ensures data integrity at the
|
||||
expense of losing some performance.
|
||||
|
||||
Storage devices that properly support 'discard_zeroes_data' are
|
||||
increasingly whitelisted in the kernel and can thus be trusted.
|
||||
|
||||
For trusted devices, the following dm-raid module parameter can be set
|
||||
to safely enable discard support for RAID 4/5/6:
|
||||
'devices_handle_discards_safely'
|
||||
|
||||
|
||||
Version History
|
||||
---------------
|
||||
1.0.0 Initial version. Support for RAID 4/5/6
|
||||
@@ -255,5 +224,3 @@ Version History
|
||||
New status (STATUSTYPE_INFO) fields: sync_action and mismatch_cnt.
|
||||
1.5.1 Add ability to restore transiently failed devices on resume.
|
||||
1.5.2 'mismatch_cnt' is zero unless [last_]sync_action is "check".
|
||||
1.6.0 Add discard support (and devices_handle_discard_safely module param).
|
||||
1.7.0 Add support for MD RAID0 mappings.
|
||||
|
@@ -41,13 +41,9 @@ useless and be disabled, returning errors. So it is important to monitor
|
||||
the amount of free space and expand the <COW device> before it fills up.
|
||||
|
||||
<persistent?> is P (Persistent) or N (Not persistent - will not survive
|
||||
after reboot). O (Overflow) can be added as a persistent store option
|
||||
to allow userspace to advertise its support for seeing "Overflow" in the
|
||||
snapshot status. So supported store types are "P", "PO" and "N".
|
||||
|
||||
The difference between persistent and transient is with transient
|
||||
snapshots less metadata must be saved on disk - they can be kept in
|
||||
memory by the kernel.
|
||||
after reboot).
|
||||
The difference is that for transient snapshots less metadata must be
|
||||
saved on disk - they can be kept in memory by the kernel.
|
||||
|
||||
|
||||
* snapshot-merge <origin> <COW device> <persistent> <chunksize>
|
||||
|
@@ -13,14 +13,9 @@ the range specified.
|
||||
The I/O statistics counters for each step-sized area of a region are
|
||||
in the same format as /sys/block/*/stat or /proc/diskstats (see:
|
||||
Documentation/iostats.txt). But two extra counters (12 and 13) are
|
||||
provided: total time spent reading and writing. When the histogram
|
||||
argument is used, the 14th parameter is reported that represents the
|
||||
histogram of latencies. All these counters may be accessed by sending
|
||||
the @stats_print message to the appropriate DM device via dmsetup.
|
||||
|
||||
The reported times are in milliseconds and the granularity depends on
|
||||
the kernel ticks. When the option precise_timestamps is used, the
|
||||
reported times are in nanoseconds.
|
||||
provided: total time spent reading and writing in milliseconds. All
|
||||
these counters may be accessed by sending the @stats_print message to
|
||||
the appropriate DM device via dmsetup.
|
||||
|
||||
Each region has a corresponding unique identifier, which we call a
|
||||
region_id, that is assigned when the region is created. The region_id
|
||||
@@ -38,9 +33,7 @@ memory is used by reading
|
||||
Messages
|
||||
========
|
||||
|
||||
@stats_create <range> <step>
|
||||
[<number_of_optional_arguments> <optional_arguments>...]
|
||||
[<program_id> [<aux_data>]]
|
||||
@stats_create <range> <step> [<program_id> [<aux_data>]]
|
||||
|
||||
Create a new region and return the region_id.
|
||||
|
||||
@@ -55,29 +48,6 @@ Messages
|
||||
"/<number_of_areas>" - the range is subdivided into the specified
|
||||
number of areas.
|
||||
|
||||
<number_of_optional_arguments>
|
||||
The number of optional arguments
|
||||
|
||||
<optional_arguments>
|
||||
The following optional arguments are supported
|
||||
precise_timestamps - use precise timer with nanosecond resolution
|
||||
instead of the "jiffies" variable. When this argument is
|
||||
used, the resulting times are in nanoseconds instead of
|
||||
milliseconds. Precise timestamps are a little bit slower
|
||||
to obtain than jiffies-based timestamps.
|
||||
histogram:n1,n2,n3,n4,... - collect histogram of latencies. The
|
||||
numbers n1, n2, etc are times that represent the boundaries
|
||||
of the histogram. If precise_timestamps is not used, the
|
||||
times are in milliseconds, otherwise they are in
|
||||
nanoseconds. For each range, the kernel will report the
|
||||
number of requests that completed within this range. For
|
||||
example, if we use "histogram:10,20,30", the kernel will
|
||||
report four numbers a:b:c:d. a is the number of requests
|
||||
that took 0-10 ms to complete, b is the number of requests
|
||||
that took 10-20 ms to complete, c is the number of requests
|
||||
that took 20-30 ms to complete and d is the number of
|
||||
requests that took more than 30 ms to complete.
|
||||
|
||||
<program_id>
|
||||
An optional parameter. A name that uniquely identifies
|
||||
the userspace owner of the range. This groups ranges together
|
||||
@@ -85,9 +55,6 @@ Messages
|
||||
created and ignore those created by others.
|
||||
The kernel returns this string back in the output of
|
||||
@stats_list message, but it doesn't use it for anything else.
|
||||
If we omit the number of optional arguments, program id must not
|
||||
be a number, otherwise it would be interpreted as the number of
|
||||
optional arguments.
|
||||
|
||||
<aux_data>
|
||||
An optional parameter. A word that provides auxiliary data
|
||||
@@ -121,10 +88,6 @@ Messages
|
||||
|
||||
Output format:
|
||||
<region_id>: <start_sector>+<length> <step> <program_id> <aux_data>
|
||||
precise_timestamps histogram:n1,n2,n3,...
|
||||
|
||||
The strings "precise_timestamps" and "histogram" are printed only
|
||||
if they were specified when creating the region.
|
||||
|
||||
@stats_print <region_id> [<starting_line> <number_of_lines>]
|
||||
|
||||
@@ -205,7 +168,7 @@ statistics on them:
|
||||
|
||||
dmsetup message vol 0 @stats_create - /100
|
||||
|
||||
Set the auxiliary data string to "foo bar baz" (the escape for each
|
||||
Set the auxillary data string to "foo bar baz" (the escape for each
|
||||
space must also be escaped, otherwise the shell will consume them):
|
||||
|
||||
dmsetup message vol 0 @stats_set_aux 0 foo\\ bar\\ baz
|
||||
|
@@ -296,7 +296,7 @@ ii) Status
|
||||
underlying device. When this is enabled when loading the table,
|
||||
it can get disabled if the underlying device doesn't support it.
|
||||
|
||||
ro|rw|out_of_data_space
|
||||
ro|rw
|
||||
If the pool encounters certain types of device failures it will
|
||||
drop into a read-only metadata mode in which no changes to
|
||||
the pool metadata (like allocating new blocks) are permitted.
|
||||
@@ -314,13 +314,6 @@ ii) Status
|
||||
module parameter can be used to change this timeout -- it
|
||||
defaults to 60 seconds but may be disabled using a value of 0.
|
||||
|
||||
needs_check
|
||||
A metadata operation has failed, resulting in the needs_check
|
||||
flag being set in the metadata's superblock. The metadata
|
||||
device must be deactivated and checked/repaired before the
|
||||
thin-pool can be made fully operational again. '-' indicates
|
||||
needs_check is not set.
|
||||
|
||||
iii) Messages
|
||||
|
||||
create_thin <dev id>
|
||||
|
@@ -18,11 +18,11 @@ Construction Parameters
|
||||
|
||||
0 is the original format used in the Chromium OS.
|
||||
The salt is appended when hashing, digests are stored continuously and
|
||||
the rest of the block is padded with zeroes.
|
||||
the rest of the block is padded with zeros.
|
||||
|
||||
1 is the current format that should be used for new devices.
|
||||
The salt is prepended when hashing and each digest is
|
||||
padded with zeroes to the power of two.
|
||||
padded with zeros to the power of two.
|
||||
|
||||
<dev>
|
||||
This is the device containing data, the integrity of which needs to be
|
||||
@@ -79,37 +79,6 @@ restart_on_corruption
|
||||
not compatible with ignore_corruption and requires user space support to
|
||||
avoid restart loops.
|
||||
|
||||
ignore_zero_blocks
|
||||
Do not verify blocks that are expected to contain zeroes and always return
|
||||
zeroes instead. This may be useful if the partition contains unused blocks
|
||||
that are not guaranteed to contain zeroes.
|
||||
|
||||
use_fec_from_device <fec_dev>
|
||||
Use forward error correction (FEC) to recover from corruption if hash
|
||||
verification fails. Use encoding data from the specified device. This
|
||||
may be the same device where data and hash blocks reside, in which case
|
||||
fec_start must be outside data and hash areas.
|
||||
|
||||
If the encoding data covers additional metadata, it must be accessible
|
||||
on the hash device after the hash blocks.
|
||||
|
||||
Note: block sizes for data and hash devices must match. Also, if the
|
||||
verity <dev> is encrypted the <fec_dev> should be too.
|
||||
|
||||
fec_roots <num>
|
||||
Number of generator roots. This equals to the number of parity bytes in
|
||||
the encoding data. For example, in RS(M, N) encoding, the number of roots
|
||||
is M-N.
|
||||
|
||||
fec_blocks <num>
|
||||
The number of encoding data blocks on the FEC device. The block size for
|
||||
the FEC device is <data_block_size>.
|
||||
|
||||
fec_start <offset>
|
||||
This is the offset, in <data_block_size> blocks, from the start of the
|
||||
FEC device to the beginning of the encoding data.
|
||||
|
||||
|
||||
Theory of operation
|
||||
===================
|
||||
|
||||
@@ -129,11 +98,6 @@ per-block basis. This allows for a lightweight hash computation on first read
|
||||
into the page cache. Block hashes are stored linearly, aligned to the nearest
|
||||
block size.
|
||||
|
||||
If forward error correction (FEC) support is enabled any recovery of
|
||||
corrupted data will be verified using the cryptographic hash of the
|
||||
corresponding data. This is why combining error correction with
|
||||
integrity checking is essential.
|
||||
|
||||
Hash Tree
|
||||
---------
|
||||
|
||||
|
@@ -50,7 +50,6 @@
|
||||
@top_srcdir@/lib/misc/lvm-file.h
|
||||
@top_srcdir@/lib/misc/lvm-flock.h
|
||||
@top_srcdir@/lib/misc/lvm-globals.h
|
||||
@top_srcdir@/lib/misc/lvm-maths.h
|
||||
@top_srcdir@/lib/misc/lvm-percent.h
|
||||
@top_srcdir@/lib/misc/lvm-signal.h
|
||||
@top_srcdir@/lib/misc/lvm-string.h
|
||||
@@ -59,7 +58,6 @@
|
||||
@top_srcdir@/lib/misc/util.h
|
||||
@top_srcdir@/lib/mm/memlock.h
|
||||
@top_srcdir@/lib/mm/xlate.h
|
||||
@top_srcdir@/lib/notify/lvmnotify.h
|
||||
@top_srcdir@/lib/properties/prop_common.h
|
||||
@top_srcdir@/lib/report/properties.h
|
||||
@top_srcdir@/lib/report/report.h
|
||||
|
@@ -264,15 +264,9 @@
|
||||
/* Define to 1 if you have the <limits.h> header file. */
|
||||
#undef HAVE_LIMITS_H
|
||||
|
||||
/* Define to 1 if you have the <linux/fiemap.h> header file. */
|
||||
#undef HAVE_LINUX_FIEMAP_H
|
||||
|
||||
/* Define to 1 if you have the <linux/fs.h> header file. */
|
||||
#undef HAVE_LINUX_FS_H
|
||||
|
||||
/* Define to 1 if you have the <linux/magic.h> header file. */
|
||||
#undef HAVE_LINUX_MAGIC_H
|
||||
|
||||
/* Define to 1 if you have the <locale.h> header file. */
|
||||
#undef HAVE_LOCALE_H
|
||||
|
||||
@@ -637,9 +631,6 @@
|
||||
/* The path to 'modprobe', if available. */
|
||||
#undef MODPROBE_CMD
|
||||
|
||||
/* Define to 1 to include code that uses dbus notification. */
|
||||
#undef NOTIFYDBUS_SUPPORT
|
||||
|
||||
/* Define to 1 to enable O_DIRECT support. */
|
||||
#undef O_DIRECT_SUPPORT
|
||||
|
||||
|
@@ -76,7 +76,6 @@ SOURCES =\
|
||||
filters/filter-partitioned.c \
|
||||
filters/filter-type.c \
|
||||
filters/filter-usable.c \
|
||||
filters/filter-internal.c \
|
||||
format_text/archive.c \
|
||||
format_text/archiver.c \
|
||||
format_text/export.c \
|
||||
@@ -112,13 +111,11 @@ SOURCES =\
|
||||
misc/lvm-file.c \
|
||||
misc/lvm-flock.c \
|
||||
misc/lvm-globals.c \
|
||||
misc/lvm-maths.c \
|
||||
misc/lvm-signal.c \
|
||||
misc/lvm-string.c \
|
||||
misc/lvm-wrappers.c \
|
||||
misc/lvm-percent.c \
|
||||
mm/memlock.c \
|
||||
notify/lvmnotify.c \
|
||||
properties/prop_common.c \
|
||||
report/properties.c \
|
||||
report/report.c \
|
||||
@@ -218,7 +215,6 @@ ifeq ($(MAKECMDGOALS),distclean)
|
||||
format_pool \
|
||||
snapshot \
|
||||
mirror \
|
||||
notify \
|
||||
raid \
|
||||
replicator \
|
||||
thin \
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@@ -253,9 +253,8 @@ int lv_status(struct cmd_context *cmd, const struct lv_segment *lv_seg,
|
||||
int lv_cache_status(const struct logical_volume *cache_lv,
|
||||
struct lv_status_cache **status)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int lv_check_not_in_use(const struct logical_volume *lv, int error_if_used)
|
||||
int lv_check_not_in_use(const struct logical_volume *lv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -288,6 +287,18 @@ int lv_raid_message(const struct logical_volume *lv, const char *msg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int lv_cache_block_info(struct logical_volume *lv,
|
||||
uint32_t *chunk_size, uint64_t *dirty_count,
|
||||
uint64_t *used_count, uint64_t *total_count)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int lv_cache_policy_info(struct logical_volume *lv,
|
||||
const char **policy_name, int *policy_argc,
|
||||
const char ***policy_argv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int lv_thin_pool_percent(const struct logical_volume *lv, int metadata,
|
||||
dm_percent_t *percent)
|
||||
{
|
||||
@@ -592,24 +603,7 @@ int module_present(struct cmd_context *cmd, const char *target_name)
|
||||
#ifdef MODPROBE_CMD
|
||||
char module[128];
|
||||
const char *argv[] = { MODPROBE_CMD, module, NULL };
|
||||
#endif
|
||||
struct stat st;
|
||||
char path[PATH_MAX];
|
||||
int i = dm_snprintf(path, (sizeof(path) - 1), "%smodule/dm_%s",
|
||||
dm_sysfs_dir(), target_name);
|
||||
|
||||
if (i > 0) {
|
||||
while (path[--i] != '/') /* stop on dm_ */
|
||||
if (path[i] == '-')
|
||||
path[i] = '_'; /* replace '-' with '_' */
|
||||
|
||||
if ((lstat(path, &st) == 0) && S_ISDIR(st.st_mode)) {
|
||||
log_debug_activation("Module directory %s exists.", path);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MODPROBE_CMD
|
||||
if (dm_snprintf(module, sizeof(module), "dm-%s", target_name) < 0) {
|
||||
log_error("module_present module name too long: %s",
|
||||
target_name);
|
||||
@@ -621,33 +615,25 @@ int module_present(struct cmd_context *cmd, const char *target_name)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int target_present_version(struct cmd_context *cmd, const char *target_name,
|
||||
int use_modprobe,
|
||||
uint32_t *maj, uint32_t *min, uint32_t *patchlevel)
|
||||
int target_present(struct cmd_context *cmd, const char *target_name,
|
||||
int use_modprobe)
|
||||
{
|
||||
if (!activation()) {
|
||||
log_error(INTERNAL_ERROR "Target present version called when activation is disabled.");
|
||||
uint32_t maj, min, patchlevel;
|
||||
|
||||
if (!activation())
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef MODPROBE_CMD
|
||||
if (use_modprobe) {
|
||||
if (target_version(target_name, maj, min, patchlevel))
|
||||
if (target_version(target_name, &maj, &min, &patchlevel))
|
||||
return 1;
|
||||
|
||||
if (!module_present(cmd, target_name))
|
||||
return_0;
|
||||
}
|
||||
#endif
|
||||
return target_version(target_name, maj, min, patchlevel);
|
||||
}
|
||||
|
||||
int target_present(struct cmd_context *cmd, const char *target_name,
|
||||
int use_modprobe)
|
||||
{
|
||||
uint32_t maj, min, patchlevel;
|
||||
|
||||
return target_present_version(cmd, target_name, use_modprobe,
|
||||
&maj, &min, &patchlevel);
|
||||
return target_version(target_name, &maj, &min, &patchlevel);
|
||||
}
|
||||
|
||||
static int _lv_info(struct cmd_context *cmd, const struct logical_volume *lv,
|
||||
@@ -674,44 +660,16 @@ static int _lv_info(struct cmd_context *cmd, const struct logical_volume *lv,
|
||||
/* New thin-pool has no layer, but -tpool suffix needs to be queried */
|
||||
if (!use_layer && lv_is_new_thin_pool(lv)) {
|
||||
/* Check if there isn't existing old thin pool mapping in the table */
|
||||
if (!dev_manager_info(cmd, lv, NULL, 0, 0, &dminfo, NULL, NULL))
|
||||
if (!dev_manager_info(cmd->mem, lv, NULL, 0, 0, &dminfo, NULL, NULL))
|
||||
return_0;
|
||||
if (!dminfo.exists)
|
||||
use_layer = 1;
|
||||
}
|
||||
|
||||
if (seg_status) {
|
||||
/* TODO: for now it's mess with seg_status */
|
||||
if (seg_status)
|
||||
seg_status->seg = seg;
|
||||
if (lv_is_merging_cow(lv)) {
|
||||
if (lv_has_target_type(cmd->mem, origin_from_cow(lv), NULL, TARGET_NAME_SNAPSHOT_MERGE)) {
|
||||
/*
|
||||
* When the snapshot-merge has not yet started, query COW LVs as is.
|
||||
* When merge is in progress, query merging origin LV instead.
|
||||
* COW volume is already mapped as error target in this case.
|
||||
*/
|
||||
lv = origin_from_cow(lv);
|
||||
seg_status->seg = first_seg(lv);
|
||||
log_debug_activation("Snapshot merge is in progress, querying status of %s instead.",
|
||||
display_lvname(lv));
|
||||
}
|
||||
} else if (!use_layer && lv_is_origin(lv) && !lv_is_external_origin(lv)) {
|
||||
/*
|
||||
* Query status for 'layered' (-real) device most of the time,
|
||||
* only when snapshot merge started, query its progress.
|
||||
* TODO: single LV may need couple status to be exposed at once....
|
||||
* but this needs more logical background
|
||||
*/
|
||||
if (!lv_is_merging_origin(lv) ||
|
||||
!lv_has_target_type(cmd->mem, origin_from_cow(lv), NULL, TARGET_NAME_SNAPSHOT_MERGE))
|
||||
use_layer = 1;
|
||||
} else if (lv_is_cow(lv)) {
|
||||
/* Hadle fictional lvm2 snapshot and query snapshotX volume */
|
||||
seg_status->seg = find_snapshot(lv);
|
||||
}
|
||||
}
|
||||
|
||||
if (!dev_manager_info(cmd, lv,
|
||||
if (!dev_manager_info(cmd->mem, lv,
|
||||
(use_layer) ? lv_layer(lv) : NULL,
|
||||
with_open_count, with_read_ahead,
|
||||
&dminfo, (info) ? &info->read_ahead : NULL,
|
||||
@@ -805,8 +763,7 @@ int lv_info_with_seg_status(struct cmd_context *cmd, const struct logical_volume
|
||||
#define OPEN_COUNT_CHECK_RETRIES 25
|
||||
#define OPEN_COUNT_CHECK_USLEEP_DELAY 200000
|
||||
|
||||
/* Only report error if error_if_used is set */
|
||||
int lv_check_not_in_use(const struct logical_volume *lv, int error_if_used)
|
||||
int lv_check_not_in_use(const struct logical_volume *lv)
|
||||
{
|
||||
struct lvinfo info;
|
||||
unsigned int open_count_check_retries;
|
||||
@@ -817,22 +774,14 @@ int lv_check_not_in_use(const struct logical_volume *lv, int error_if_used)
|
||||
/* If sysfs is not used, use open_count information only. */
|
||||
if (dm_sysfs_dir()) {
|
||||
if (dm_device_has_holders(info.major, info.minor)) {
|
||||
if (error_if_used)
|
||||
log_error("Logical volume %s is used by another device.",
|
||||
display_lvname(lv));
|
||||
else
|
||||
log_debug_activation("Logical volume %s is used by another device.",
|
||||
display_lvname(lv));
|
||||
log_error("Logical volume %s is used by another device.",
|
||||
display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dm_device_has_mounted_fs(info.major, info.minor)) {
|
||||
if (error_if_used)
|
||||
log_error("Logical volume %s contains a filesystem in use.",
|
||||
display_lvname(lv));
|
||||
else
|
||||
log_debug_activation("Logical volume %s contains a filesystem in use.",
|
||||
display_lvname(lv));
|
||||
log_error("Logical volume %s contains a filesystem in use.",
|
||||
display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -840,10 +789,8 @@ int lv_check_not_in_use(const struct logical_volume *lv, int error_if_used)
|
||||
open_count_check_retries = retry_deactivation() ? OPEN_COUNT_CHECK_RETRIES : 1;
|
||||
while (info.open_count > 0 && open_count_check_retries--) {
|
||||
if (!open_count_check_retries) {
|
||||
if (error_if_used)
|
||||
log_error("Logical volume %s in use.", display_lvname(lv));
|
||||
else
|
||||
log_debug_activation("Logical volume %s in use.", display_lvname(lv));
|
||||
log_error("Logical volume %s in use.",
|
||||
display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1120,29 +1067,19 @@ int lv_cache_status(const struct logical_volume *cache_lv,
|
||||
struct dev_manager *dm;
|
||||
struct lv_segment *cache_seg;
|
||||
|
||||
if (lv_is_cache_pool(cache_lv)) {
|
||||
if (dm_list_empty(&cache_lv->segs_using_this_lv) ||
|
||||
!(cache_seg = get_only_segment_using_this_lv(cache_lv))) {
|
||||
log_error(INTERNAL_ERROR "Cannot check status for unused cache pool %s.",
|
||||
display_lvname(cache_lv));
|
||||
return 0;
|
||||
}
|
||||
if (lv_is_cache_pool(cache_lv) && !dm_list_empty(&cache_lv->segs_using_this_lv)) {
|
||||
if (!(cache_seg = get_only_segment_using_this_lv(cache_lv)))
|
||||
return_0;
|
||||
cache_lv = cache_seg->lv;
|
||||
}
|
||||
|
||||
if (lv_is_pending_delete(cache_lv)) {
|
||||
log_error("Cannot check status for deleted cache volume %s.",
|
||||
display_lvname(cache_lv));
|
||||
if (lv_is_pending_delete(cache_lv))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!lv_info(cache_lv->vg->cmd, cache_lv, 0, NULL, 0, 0)) {
|
||||
log_error("Cannot check status for locally inactive cache volume %s.",
|
||||
display_lvname(cache_lv));
|
||||
if (!lv_info(cache_lv->vg->cmd, cache_lv, 0, NULL, 0, 0))
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_debug_activation("Checking status for cache volume %s.",
|
||||
log_debug_activation("Checking cache status for LV %s.",
|
||||
display_lvname(cache_lv));
|
||||
|
||||
if (!(dm = dev_manager_create(cache_lv->vg->cmd, cache_lv->vg->name, 1)))
|
||||
@@ -1223,13 +1160,13 @@ int lv_thin_pool_transaction_id(const struct logical_volume *lv,
|
||||
if (!lv_info(lv->vg->cmd, lv, 1, NULL, 0, 0))
|
||||
return 0;
|
||||
|
||||
log_debug_activation("Checking thin-pool transaction id for LV %s.",
|
||||
log_debug_activation("Checking thin-pool percent for LV %s.",
|
||||
display_lvname(lv));
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
|
||||
return_0;
|
||||
|
||||
if (!(r = dev_manager_thin_pool_status(dm, lv, &status, 0)))
|
||||
if (!(r = dev_manager_thin_pool_status(dm, lv, &status, 1)))
|
||||
stack;
|
||||
else
|
||||
*transaction_id = status->transaction_id;
|
||||
@@ -1266,10 +1203,8 @@ static int _lv_active(struct cmd_context *cmd, const struct logical_volume *lv)
|
||||
struct lvinfo info;
|
||||
|
||||
if (!lv_info(cmd, lv, 0, &info, 0, 0)) {
|
||||
log_debug("Cannot determine activation status of %s%s.",
|
||||
display_lvname(lv),
|
||||
activation() ? "" : " (no device driver)");
|
||||
return 0;
|
||||
stack;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return info.exists;
|
||||
@@ -1394,7 +1329,7 @@ int lvs_in_vg_opened(const struct volume_group *vg)
|
||||
if (lv_is_visible(lvl->lv))
|
||||
count += (_lv_open_count(vg->cmd, lvl->lv) > 0);
|
||||
|
||||
log_debug_activation("Counted %d open LVs in VG %s.", count, vg->name);
|
||||
log_debug_activation("Counted %d open LVs in VG %s", count, vg->name);
|
||||
|
||||
return count;
|
||||
}
|
||||
@@ -1456,9 +1391,9 @@ static int _lv_is_active(const struct logical_volume *lv,
|
||||
* Old users of this function will never be affected by this,
|
||||
* since they are only concerned about active vs. not active.
|
||||
* New users of this function who specifically ask for 'exclusive'
|
||||
* will be given a warning message.
|
||||
* will be given an error message.
|
||||
*/
|
||||
log_warn("WARNING: Unable to determine exclusivity of %s.", display_lvname(lv));
|
||||
log_error("Unable to determine exclusivity of %s.", display_lvname(lv));
|
||||
|
||||
e = 0;
|
||||
|
||||
@@ -1548,7 +1483,7 @@ static struct dm_event_handler *_create_dm_event_handler(struct cmd_context *cmd
|
||||
if (dm_event_handler_set_dmeventd_path(dmevh, find_config_tree_str(cmd, dmeventd_executable_CFG, NULL)))
|
||||
goto_bad;
|
||||
|
||||
if (dso && dm_event_handler_set_dso(dmevh, dso))
|
||||
if (dm_event_handler_set_dso(dmevh, dso))
|
||||
goto_bad;
|
||||
|
||||
if (dm_event_handler_set_uuid(dmevh, dmuuid))
|
||||
@@ -1592,39 +1527,6 @@ static char *_build_target_uuid(struct cmd_context *cmd, const struct logical_vo
|
||||
return build_dm_uuid(cmd->mem, lv, layer);
|
||||
}
|
||||
|
||||
static int _device_registered_with_dmeventd(struct cmd_context *cmd, const struct logical_volume *lv, int *pending, const char **dso)
|
||||
{
|
||||
char *uuid;
|
||||
enum dm_event_mask evmask = 0;
|
||||
struct dm_event_handler *dmevh;
|
||||
|
||||
*pending = 0;
|
||||
|
||||
if (!(uuid = _build_target_uuid(cmd, lv)))
|
||||
return_0;
|
||||
|
||||
if (!(dmevh = _create_dm_event_handler(cmd, uuid, NULL, 0, DM_EVENT_ALL_ERRORS)))
|
||||
return_0;
|
||||
|
||||
if (dm_event_get_registered_device(dmevh, 0)) {
|
||||
dm_event_handler_destroy(dmevh);
|
||||
return 0;
|
||||
}
|
||||
|
||||
evmask = dm_event_handler_get_event_mask(dmevh);
|
||||
if (evmask & DM_EVENT_REGISTRATION_PENDING) {
|
||||
*pending = 1;
|
||||
evmask &= ~DM_EVENT_REGISTRATION_PENDING;
|
||||
}
|
||||
|
||||
if (dso && (*dso = dm_event_handler_get_dso(dmevh)) && !(*dso = dm_pool_strdup(cmd->mem, *dso)))
|
||||
log_error("Failed to duplicate dso name.");
|
||||
|
||||
dm_event_handler_destroy(dmevh);
|
||||
|
||||
return evmask;
|
||||
}
|
||||
|
||||
int target_registered_with_dmeventd(struct cmd_context *cmd, const char *dso,
|
||||
const struct logical_volume *lv, int *pending)
|
||||
{
|
||||
@@ -1707,8 +1609,6 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
|
||||
uint32_t s;
|
||||
static const struct lv_activate_opts zlaopts = { 0 };
|
||||
struct lvinfo info;
|
||||
const char *dso = NULL;
|
||||
int new_unmonitor;
|
||||
|
||||
if (!laopts)
|
||||
laopts = &zlaopts;
|
||||
@@ -1723,23 +1623,6 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
|
||||
if (monitor && !dmeventd_monitor_mode())
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Activation of unused cache-pool activates metadata device as
|
||||
* a public LV for clearing purpose.
|
||||
* FIXME:
|
||||
* As VG lock is held across whole operation unmonitored volume
|
||||
* is usually OK since dmeventd couldn't do anything.
|
||||
* However in case command would have crashed, such LV is
|
||||
* left unmonitored and may potentially require dmeventd.
|
||||
*/
|
||||
if ((lv_is_cache_pool_data(lv) || lv_is_cache_pool_metadata(lv)) &&
|
||||
!lv_is_used_cache_pool((find_pool_seg(first_seg(lv))->lv))) {
|
||||
log_debug_activation("Skipping %smonitor of %s.%s",
|
||||
(monitor) ? "" : "un", display_lvname(lv),
|
||||
(monitor) ? " Cache pool activation for clearing only." : "");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allow to unmonitor thin pool via explicit pool unmonitor
|
||||
* or unmonitor before the last thin pool user deactivation
|
||||
@@ -1774,8 +1657,7 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
|
||||
/*
|
||||
* In case this LV is a snapshot origin, we instead monitor
|
||||
* each of its respective snapshots. The origin itself may
|
||||
* also need to be monitored if it is a mirror, for example,
|
||||
* so fall through to process it afterwards.
|
||||
* also need to be monitored if it is a mirror, for example.
|
||||
*/
|
||||
if (!laopts->origin_only && lv_is_origin(lv))
|
||||
dm_list_iterate_safe(snh, snht, &lv->snapshot_segs)
|
||||
@@ -1834,58 +1716,42 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
|
||||
!seg->segtype->ops->target_monitored) /* doesn't support registration */
|
||||
continue;
|
||||
|
||||
if (!monitor)
|
||||
/* When unmonitoring, obtain existing dso being used. */
|
||||
monitored = _device_registered_with_dmeventd(cmd, seg_is_snapshot(seg) ? seg->cow : seg->lv, &pending, &dso);
|
||||
else
|
||||
monitored = seg->segtype->ops->target_monitored(seg, &pending);
|
||||
monitored = seg->segtype->ops->target_monitored(seg, &pending);
|
||||
|
||||
/* FIXME: We should really try again if pending */
|
||||
monitored = (pending) ? 0 : monitored;
|
||||
|
||||
monitor_fn = NULL;
|
||||
new_unmonitor = 0;
|
||||
|
||||
if (monitor) {
|
||||
if (monitored)
|
||||
log_verbose("%s already monitored.", display_lvname(lv));
|
||||
else if (seg->segtype->ops->target_monitor_events) {
|
||||
log_verbose("Monitoring %s%s", display_lvname(lv), test_mode() ? " [Test mode: skipping this]" : "");
|
||||
else if (seg->segtype->ops->target_monitor_events)
|
||||
monitor_fn = seg->segtype->ops->target_monitor_events;
|
||||
}
|
||||
} else {
|
||||
if (!monitored)
|
||||
log_verbose("%s already not monitored.", display_lvname(lv));
|
||||
else if (dso && *dso) {
|
||||
/*
|
||||
* Divert unmonitor away from code that depends on the new segment
|
||||
* type instead of the existing one if it's changing.
|
||||
*/
|
||||
log_verbose("Not monitoring %s with %s%s", display_lvname(lv), dso, test_mode() ? " [Test mode: skipping this]" : "");
|
||||
new_unmonitor = 1;
|
||||
}
|
||||
else if (seg->segtype->ops->target_unmonitor_events)
|
||||
monitor_fn = seg->segtype->ops->target_unmonitor_events;
|
||||
}
|
||||
|
||||
/* Do [un]monitor */
|
||||
if (!monitor_fn)
|
||||
continue;
|
||||
|
||||
log_verbose("%sonitoring %s%s", monitor ? "M" : "Not m", display_lvname(lv),
|
||||
test_mode() ? " [Test mode: skipping this]" : "");
|
||||
|
||||
/* FIXME Test mode should really continue a bit further. */
|
||||
if (test_mode())
|
||||
continue;
|
||||
|
||||
if (new_unmonitor) {
|
||||
if (!target_register_events(cmd, dso, seg_is_snapshot(seg) ? seg->cow : lv, 0, 0, 10)) {
|
||||
log_error("%s: segment unmonitoring failed.",
|
||||
display_lvname(lv));
|
||||
|
||||
return 0;
|
||||
}
|
||||
} else if (monitor_fn) {
|
||||
/* FIXME specify events */
|
||||
if (!monitor_fn(seg, 0)) {
|
||||
log_error("%s: %s segment monitoring function failed.",
|
||||
display_lvname(lv), seg->segtype->name);
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
continue;
|
||||
/* FIXME specify events */
|
||||
if (!monitor_fn(seg, 0)) {
|
||||
log_error("%s: %s segment monitoring function failed.",
|
||||
display_lvname(lv), seg->segtype->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check [un]monitor results */
|
||||
/* Try a couple times if pending, but not forever... */
|
||||
@@ -1961,7 +1827,7 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
|
||||
const struct logical_volume *lv_pre_to_free = NULL;
|
||||
struct logical_volume *lv_pre_tmp;
|
||||
struct seg_list *sl;
|
||||
struct lv_segment *snap_seg;
|
||||
struct lv_segment *snap_seg;
|
||||
struct lvinfo info;
|
||||
int r = 0, lockfs = 0, flush_required = 0;
|
||||
struct detached_lv_data detached;
|
||||
@@ -2067,16 +1933,6 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
|
||||
}
|
||||
}
|
||||
|
||||
/* Flush is ATM required for the tested cases
|
||||
* NOTE: Mirror repair requires noflush for proper repair!
|
||||
* TODO: Relax this limiting condition further */
|
||||
if (!flush_required &&
|
||||
(lv_is_pvmove(lv) ||
|
||||
(!lv_is_mirror(lv) && !lv_is_thin_pool(lv) && !lv_is_thin_volume(lv)))) {
|
||||
log_debug("Requiring flush for LV %s.", display_lvname(lv));
|
||||
flush_required = 1;
|
||||
}
|
||||
|
||||
if (!monitor_dev_for_events(cmd, lv, laopts, 0))
|
||||
/* FIXME Consider aborting here */
|
||||
stack;
|
||||
@@ -2197,7 +2053,6 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
|
||||
}
|
||||
|
||||
laopts->read_only = _passes_readonly_filter(cmd, lv);
|
||||
laopts->resuming = 1;
|
||||
|
||||
if (!_lv_activate_lv(lv, laopts))
|
||||
goto_out;
|
||||
@@ -2252,7 +2107,7 @@ static int _lv_has_open_snapshots(const struct logical_volume *lv)
|
||||
int r = 0;
|
||||
|
||||
dm_list_iterate_items_gen(snap_seg, &lv->snapshot_segs, origin_list)
|
||||
if (!lv_check_not_in_use(snap_seg->cow, 1))
|
||||
if (!lv_check_not_in_use(snap_seg->cow))
|
||||
r++;
|
||||
|
||||
if (r)
|
||||
@@ -2306,7 +2161,7 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s, const struct logi
|
||||
|
||||
if (lv_is_visible(lv) || lv_is_virtual_origin(lv) ||
|
||||
lv_is_merging_thin_snapshot(lv)) {
|
||||
if (!lv_check_not_in_use(lv, 1))
|
||||
if (!lv_check_not_in_use(lv))
|
||||
goto_out;
|
||||
|
||||
if (lv_is_origin(lv) && _lv_has_open_snapshots(lv))
|
||||
@@ -2388,7 +2243,7 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((!lv->vg->cmd->partial_activation) && lv_is_partial(lv)) {
|
||||
if ((!lv->vg->cmd->partial_activation) && (lv->status & PARTIAL_LV)) {
|
||||
if (!lv_is_raid_type(lv) || !partial_raid_lv_supports_degraded_activation(lv)) {
|
||||
log_error("Refusing activation of partial LV %s. "
|
||||
"Use '--activationmode partial' to override.",
|
||||
@@ -2444,7 +2299,7 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
|
||||
if (info.exists && !info.suspended && info.live_table &&
|
||||
(info.read_only == read_only_lv(lv, laopts))) {
|
||||
r = 1;
|
||||
log_debug_activation("LV %s is already active.", display_lvname(lv));
|
||||
log_debug_activation("Volume is already active.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@@ -81,7 +81,6 @@ struct lv_activate_opts {
|
||||
* set of flags to avoid any scanning in udev. These udev
|
||||
* flags are persistent in udev db for any spurious event
|
||||
* that follows. */
|
||||
unsigned resuming; /* Set when resuming after a suspend. */
|
||||
};
|
||||
|
||||
void set_activation(int activation, int silent);
|
||||
@@ -92,9 +91,6 @@ int library_version(char *version, size_t size);
|
||||
int lvm1_present(struct cmd_context *cmd);
|
||||
|
||||
int module_present(struct cmd_context *cmd, const char *target_name);
|
||||
int target_present_version(struct cmd_context *cmd, const char *target_name,
|
||||
int use_modprobe, uint32_t *maj,
|
||||
uint32_t *min, uint32_t *patchlevel);
|
||||
int target_present(struct cmd_context *cmd, const char *target_name,
|
||||
int use_modprobe);
|
||||
int target_version(const char *target_name, uint32_t *maj,
|
||||
@@ -150,7 +146,7 @@ int lv_info_with_seg_status(struct cmd_context *cmd, const struct logical_volume
|
||||
struct lv_with_info_and_seg_status *status,
|
||||
int with_open_count, int with_read_ahead);
|
||||
|
||||
int lv_check_not_in_use(const struct logical_volume *lv, int error_if_used);
|
||||
int lv_check_not_in_use(const struct logical_volume *lv);
|
||||
|
||||
/*
|
||||
* Returns 1 if activate_lv has been set: 1 = activate; 0 = don't.
|
||||
@@ -243,28 +239,4 @@ int device_is_usable(struct device *dev, struct dev_usable_check_params check);
|
||||
*/
|
||||
void fs_unlock(void);
|
||||
|
||||
#define TARGET_NAME_CACHE "cache"
|
||||
#define TARGET_NAME_ERROR "error"
|
||||
#define TARGET_NAME_ERROR_OLD "erro" /* Truncated in older kernels */
|
||||
#define TARGET_NAME_LINEAR "linear"
|
||||
#define TARGET_NAME_MIRROR "mirror"
|
||||
#define TARGET_NAME_RAID "raid"
|
||||
#define TARGET_NAME_SNAPSHOT "snapshot"
|
||||
#define TARGET_NAME_SNAPSHOT_MERGE "snapshot-merge"
|
||||
#define TARGET_NAME_SNAPSHOT_ORIGIN "snapshot-origin"
|
||||
#define TARGET_NAME_STRIPED "striped"
|
||||
#define TARGET_NAME_THIN "thin"
|
||||
#define TARGET_NAME_THIN_POOL "thin-pool"
|
||||
#define TARGET_NAME_ZERO "zero"
|
||||
|
||||
#define MODULE_NAME_CLUSTERED_MIRROR "clog"
|
||||
#define MODULE_NAME_CACHE TARGET_NAME_CACHE
|
||||
#define MODULE_NAME_ERROR TARGET_NAME_ERROR
|
||||
#define MODULE_NAME_LOG_CLUSTERED "log-clustered"
|
||||
#define MODULE_NAME_LOG_USERSPACE "log-userspace"
|
||||
#define MODULE_NAME_MIRROR TARGET_NAME_MIRROR
|
||||
#define MODULE_NAME_SNAPSHOT TARGET_NAME_SNAPSHOT
|
||||
#define MODULE_NAME_RAID TARGET_NAME_RAID
|
||||
#define MODULE_NAME_ZERO TARGET_NAME_ZERO
|
||||
|
||||
#endif
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@@ -85,8 +85,7 @@ int read_only_lv(const struct logical_volume *lv, const struct lv_activate_opts
|
||||
static struct dm_task *_setup_task(const char *name, const char *uuid,
|
||||
uint32_t *event_nr, int task,
|
||||
uint32_t major, uint32_t minor,
|
||||
int with_open_count,
|
||||
int with_flush)
|
||||
int with_open_count)
|
||||
{
|
||||
struct dm_task *dmt;
|
||||
|
||||
@@ -111,9 +110,6 @@ static struct dm_task *_setup_task(const char *name, const char *uuid,
|
||||
if (!with_open_count && !dm_task_no_open_count(dmt))
|
||||
log_warn("WARNING: Failed to disable open_count.");
|
||||
|
||||
if (!with_flush && !dm_task_no_flush(dmt))
|
||||
log_warn("WARNING: Failed to set no_flush.");
|
||||
|
||||
return dmt;
|
||||
out:
|
||||
dm_task_destroy(dmt);
|
||||
@@ -127,7 +123,6 @@ static int _get_segment_status_from_target_params(const char *target_name,
|
||||
struct segment_type *segtype;
|
||||
|
||||
seg_status->type = SEG_STATUS_UNKNOWN;
|
||||
|
||||
/*
|
||||
* TODO: Add support for other segment types too!
|
||||
* The segment to report status for must be properly
|
||||
@@ -135,27 +130,17 @@ static int _get_segment_status_from_target_params(const char *target_name,
|
||||
* linear/striped, old snapshots and raids have proper
|
||||
* segment selected for status!
|
||||
*/
|
||||
if (!strcmp(target_name, TARGET_NAME_SNAPSHOT_MERGE) &&
|
||||
lv_is_merging_origin(seg_status->seg->lv)) {
|
||||
/* Snapshot merge has started, check snapshot status */
|
||||
if (!(segtype = get_segtype_from_string(seg_status->seg->lv->vg->cmd, TARGET_NAME_SNAPSHOT)))
|
||||
return_0;
|
||||
} else {
|
||||
if (strcmp(target_name, TARGET_NAME_CACHE) &&
|
||||
strcmp(target_name, TARGET_NAME_SNAPSHOT) &&
|
||||
strcmp(target_name, TARGET_NAME_THIN_POOL) &&
|
||||
strcmp(target_name, TARGET_NAME_THIN))
|
||||
return 1; /* TODO: Do not know how to handle yet */
|
||||
if (strcmp(target_name, "cache") && strcmp(target_name, "thin-pool"))
|
||||
return 1;
|
||||
|
||||
if (!(segtype = get_segtype_from_string(seg_status->seg->lv->vg->cmd, target_name)))
|
||||
return_0;
|
||||
if (!(segtype = get_segtype_from_string(seg_status->seg->lv->vg->cmd, target_name)))
|
||||
return_0;
|
||||
|
||||
if (segtype != seg_status->seg->segtype) {
|
||||
log_error(INTERNAL_ERROR "_get_segment_status_from_target_params: "
|
||||
"segment type %s found does not match expected segment type %s",
|
||||
segtype->name, seg_status->seg->segtype->name);
|
||||
return 0;
|
||||
}
|
||||
if (segtype != seg_status->seg->segtype) {
|
||||
log_error(INTERNAL_ERROR "_get_segment_status_from_target_params: "
|
||||
"segment type %s found does not match expected segment type %s",
|
||||
segtype->name, seg_status->seg->segtype->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (segtype_is_cache(segtype)) {
|
||||
@@ -205,7 +190,6 @@ static int _info_run(info_type_t type, const char *name, const char *dlid,
|
||||
uint64_t target_start, target_length;
|
||||
char *target_name, *target_params, *params_to_process = NULL;
|
||||
uint32_t extent_size;
|
||||
int with_flush = 1; /* TODO: arg for _info_run */
|
||||
|
||||
switch (type) {
|
||||
case INFO:
|
||||
@@ -213,7 +197,6 @@ static int _info_run(info_type_t type, const char *name, const char *dlid,
|
||||
break;
|
||||
case STATUS:
|
||||
dmtask = DM_DEVICE_STATUS;
|
||||
with_flush = 0;
|
||||
break;
|
||||
case MKNODES:
|
||||
dmtask = DM_DEVICE_MKNODES;
|
||||
@@ -224,7 +207,7 @@ static int _info_run(info_type_t type, const char *name, const char *dlid,
|
||||
}
|
||||
|
||||
if (!(dmt = _setup_task((type == MKNODES) ? name : NULL, dlid, 0, dmtask,
|
||||
major, minor, with_open_count, with_flush)))
|
||||
major, minor, with_open_count)))
|
||||
return_0;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
@@ -331,7 +314,7 @@ static int _ignore_blocked_mirror_devices(struct device *dev,
|
||||
if (!(tmp_dev = dev_create_file(buf, NULL, NULL, 0)))
|
||||
goto_out;
|
||||
|
||||
tmp_dev->dev = MKDEV((dev_t)sm->logs[0].major, (dev_t)sm->logs[0].minor);
|
||||
tmp_dev->dev = MKDEV((dev_t)sm->logs[0].major, sm->logs[0].minor);
|
||||
if (device_is_usable(tmp_dev, (struct dev_usable_check_params)
|
||||
{ .check_empty = 1,
|
||||
.check_blocked = 1,
|
||||
@@ -352,8 +335,13 @@ static int _ignore_blocked_mirror_devices(struct device *dev,
|
||||
* We avoid another system call if we can, but if a device is
|
||||
* dead, we have no choice but to look up the table too.
|
||||
*/
|
||||
if (!(dmt = _setup_task(NULL, NULL, NULL, DM_DEVICE_TABLE,
|
||||
MAJOR(dev->dev), MINOR(dev->dev), 0, 1)))
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
|
||||
goto_out;
|
||||
|
||||
if (!dm_task_set_major_minor(dmt, MAJOR(dev->dev), MINOR(dev->dev), 1))
|
||||
goto_out;
|
||||
|
||||
if (activation_checks() && !dm_task_enable_checks(dmt))
|
||||
goto_out;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
@@ -362,9 +350,8 @@ static int _ignore_blocked_mirror_devices(struct device *dev,
|
||||
do {
|
||||
next = dm_get_next_target(dmt, next, &s, &l,
|
||||
&target_type, ¶ms);
|
||||
if ((s == start) && (l == length) &&
|
||||
target_type && params) {
|
||||
if (strcmp(target_type, TARGET_NAME_MIRROR))
|
||||
if ((s == start) && (l == length)) {
|
||||
if (strcmp(target_type, "mirror"))
|
||||
goto_out;
|
||||
|
||||
if (((p = strstr(params, " block_on_error")) &&
|
||||
@@ -394,9 +381,14 @@ static int _device_is_suspended(int major, int minor)
|
||||
struct dm_info info;
|
||||
int r = 0;
|
||||
|
||||
if (!(dmt = _setup_task(NULL, NULL, NULL, DM_DEVICE_INFO,
|
||||
major, minor, 0, 0)))
|
||||
return_0;
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
|
||||
return 0;
|
||||
|
||||
if (!dm_task_set_major_minor(dmt, major, minor, 1))
|
||||
goto_out;
|
||||
|
||||
if (activation_checks() && !dm_task_enable_checks(dmt))
|
||||
goto_out;
|
||||
|
||||
if (!dm_task_run(dmt) ||
|
||||
!dm_task_get_info(dmt, &info)) {
|
||||
@@ -419,10 +411,15 @@ static int _ignore_suspended_snapshot_component(struct device *dev)
|
||||
int major1, minor1, major2, minor2;
|
||||
int r = 0;
|
||||
|
||||
if (!(dmt = _setup_task(NULL, NULL, NULL, DM_DEVICE_TABLE,
|
||||
MAJOR(dev->dev), MINOR(dev->dev), 0, 1)))
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
|
||||
return_0;
|
||||
|
||||
if (!dm_task_set_major_minor(dmt, MAJOR(dev->dev), MINOR(dev->dev), 1))
|
||||
goto_out;
|
||||
|
||||
if (activation_checks() && !dm_task_enable_checks(dmt))
|
||||
goto_out;
|
||||
|
||||
if (!dm_task_run(dmt)) {
|
||||
log_error("Failed to get state of snapshot or snapshot origin device");
|
||||
goto out;
|
||||
@@ -430,13 +427,13 @@ static int _ignore_suspended_snapshot_component(struct device *dev)
|
||||
|
||||
do {
|
||||
next = dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms);
|
||||
if (!target_type || !strcmp(target_type, TARGET_NAME_SNAPSHOT)) {
|
||||
if (!target_type || !strcmp(target_type, "snapshot")) {
|
||||
if (!params || sscanf(params, "%d:%d %d:%d", &major1, &minor1, &major2, &minor2) != 4) {
|
||||
log_error("Incorrect snapshot table found");
|
||||
goto_out;
|
||||
}
|
||||
r = r || _device_is_suspended(major1, minor1) || _device_is_suspended(major2, minor2);
|
||||
} else if (!strcmp(target_type, TARGET_NAME_SNAPSHOT_ORIGIN)) {
|
||||
} else if (!strcmp(target_type, "snapshot-origin")) {
|
||||
if (!params || sscanf(params, "%d:%d", &major1, &minor1) != 2) {
|
||||
log_error("Incorrect snapshot-origin table found");
|
||||
goto_out;
|
||||
@@ -466,26 +463,32 @@ static int _ignore_unusable_thins(struct device *dev)
|
||||
if (!(mem = dm_pool_create("unusable_thins", 128)))
|
||||
return_0;
|
||||
|
||||
if (!(dmt = _setup_task(NULL, NULL, NULL, DM_DEVICE_TABLE,
|
||||
MAJOR(dev->dev), MINOR(dev->dev), 0, 1)))
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
|
||||
goto_out;
|
||||
if (!dm_task_no_open_count(dmt))
|
||||
goto_out;
|
||||
if (!dm_task_set_major_minor(dmt, MAJOR(dev->dev), MINOR(dev->dev), 1))
|
||||
goto_out;
|
||||
|
||||
if (!dm_task_run(dmt)) {
|
||||
log_error("Failed to get state of mapped device.");
|
||||
goto out;
|
||||
}
|
||||
dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms);
|
||||
if (!params || sscanf(params, "%d:%d", &major, &minor) != 2) {
|
||||
if (!params || sscanf(params, "%d:%d", &minor, &major) != 2) {
|
||||
log_error("Failed to get thin-pool major:minor for thin device %d:%d.",
|
||||
(int)MAJOR(dev->dev), (int)MINOR(dev->dev));
|
||||
goto out;
|
||||
}
|
||||
dm_task_destroy(dmt);
|
||||
|
||||
if (!(dmt = _setup_task(NULL, NULL, NULL, DM_DEVICE_STATUS,
|
||||
major, minor, 0, 0)))
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
|
||||
goto_out;
|
||||
if (!dm_task_no_flush(dmt))
|
||||
log_warn("Can't set no_flush.");
|
||||
if (!dm_task_no_open_count(dmt))
|
||||
goto_out;
|
||||
if (!dm_task_set_major_minor(dmt, minor, major, 1))
|
||||
goto_out;
|
||||
|
||||
if (!dm_task_run(dmt)) {
|
||||
log_error("Failed to get state of mapped device.");
|
||||
goto out;
|
||||
@@ -539,10 +542,15 @@ int device_is_usable(struct device *dev, struct dev_usable_check_params check)
|
||||
int only_error_target = 1;
|
||||
int r = 0;
|
||||
|
||||
if (!(dmt = _setup_task(NULL, NULL, NULL, DM_DEVICE_STATUS,
|
||||
MAJOR(dev->dev), MINOR(dev->dev), 0, 0)))
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
|
||||
return_0;
|
||||
|
||||
if (!dm_task_set_major_minor(dmt, MAJOR(dev->dev), MINOR(dev->dev), 1))
|
||||
goto_out;
|
||||
|
||||
if (activation_checks() && !dm_task_enable_checks(dmt))
|
||||
goto_out;
|
||||
|
||||
if (!dm_task_run(dmt)) {
|
||||
log_error("Failed to get state of mapped device");
|
||||
goto out;
|
||||
@@ -593,7 +601,7 @@ int device_is_usable(struct device *dev, struct dev_usable_check_params check)
|
||||
next = dm_get_next_target(dmt, next, &start, &length,
|
||||
&target_type, ¶ms);
|
||||
|
||||
if (check.check_blocked && target_type && !strcmp(target_type, TARGET_NAME_MIRROR)) {
|
||||
if (check.check_blocked && target_type && !strcmp(target_type, "mirror")) {
|
||||
if (ignore_lvm_mirrors()) {
|
||||
log_debug_activation("%s: Scanning mirror devices is disabled.", dev_name(dev));
|
||||
goto out;
|
||||
@@ -628,20 +636,20 @@ int device_is_usable(struct device *dev, struct dev_usable_check_params check)
|
||||
* in a stack - use proper dm tree to check this instead.
|
||||
*/
|
||||
if (check.check_suspended && target_type &&
|
||||
(!strcmp(target_type, TARGET_NAME_SNAPSHOT) || !strcmp(target_type, TARGET_NAME_SNAPSHOT_ORIGIN)) &&
|
||||
(!strcmp(target_type, "snapshot") || !strcmp(target_type, "snapshot-origin")) &&
|
||||
_ignore_suspended_snapshot_component(dev)) {
|
||||
log_debug_activation("%s: %s device %s not usable.", dev_name(dev), target_type, name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* TODO: extend check struct ? */
|
||||
if (target_type && !strcmp(target_type, TARGET_NAME_THIN) &&
|
||||
if (target_type && !strcmp(target_type, "thin") &&
|
||||
!_ignore_unusable_thins(dev)) {
|
||||
log_debug_activation("%s: %s device %s not usable.", dev_name(dev), target_type, name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (target_type && strcmp(target_type, TARGET_NAME_ERROR))
|
||||
if (target_type && strcmp(target_type, "error"))
|
||||
only_error_target = 0;
|
||||
} while (next);
|
||||
|
||||
@@ -663,32 +671,7 @@ int device_is_usable(struct device *dev, struct dev_usable_check_params check)
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* If active LVs were activated by a version of LVM2 before 2.02.00 we must
|
||||
* perform additional checks to find them because they do not have the LVM-
|
||||
* prefix on their dm uuids.
|
||||
* As of 2.02.150, we've chosen to disable this compatibility arbitrarily if
|
||||
* we're running kernel version 3 or above.
|
||||
*/
|
||||
#define MIN_KERNEL_MAJOR 3
|
||||
|
||||
static int _original_uuid_format_check_required(struct cmd_context *cmd)
|
||||
{
|
||||
static int _kernel_major = 0;
|
||||
|
||||
if (!_kernel_major) {
|
||||
if ((sscanf(cmd->kernel_vsn, "%d", &_kernel_major) == 1) &&
|
||||
(_kernel_major >= MIN_KERNEL_MAJOR))
|
||||
log_debug_activation("Skipping checks for old devices without " UUID_PREFIX
|
||||
" dm uuid prefix (kernel vsn %d >= %d).", _kernel_major, MIN_KERNEL_MAJOR);
|
||||
else
|
||||
_kernel_major = -1;
|
||||
}
|
||||
|
||||
return (_kernel_major == -1);
|
||||
}
|
||||
|
||||
static int _info(struct cmd_context *cmd, const char *dlid, int with_open_count, int with_read_ahead,
|
||||
static int _info(const char *dlid, int with_open_count, int with_read_ahead,
|
||||
struct dm_info *dminfo, uint32_t *read_ahead,
|
||||
struct lv_seg_status *seg_status)
|
||||
{
|
||||
@@ -717,10 +700,6 @@ static int _info(struct cmd_context *cmd, const char *dlid, int with_open_count,
|
||||
}
|
||||
}
|
||||
|
||||
/* Must we still check for the pre-2.02.00 dm uuid format? */
|
||||
if (!_original_uuid_format_check_required(cmd))
|
||||
return r;
|
||||
|
||||
/* Check for dlid before UUID_PREFIX was added */
|
||||
if ((r = _info_run(seg_status ? STATUS : INFO, NULL, dlid + sizeof(UUID_PREFIX) - 1,
|
||||
dminfo, read_ahead, seg_status, with_open_count,
|
||||
@@ -735,7 +714,7 @@ static int _info_by_dev(uint32_t major, uint32_t minor, struct dm_info *info)
|
||||
return _info_run(INFO, NULL, NULL, info, NULL, 0, 0, 0, major, minor);
|
||||
}
|
||||
|
||||
int dev_manager_info(struct cmd_context *cmd, const struct logical_volume *lv,
|
||||
int dev_manager_info(struct dm_pool *mem, const struct logical_volume *lv,
|
||||
const char *layer,
|
||||
int with_open_count, int with_read_ahead,
|
||||
struct dm_info *dminfo, uint32_t *read_ahead,
|
||||
@@ -744,19 +723,19 @@ int dev_manager_info(struct cmd_context *cmd, const struct logical_volume *lv,
|
||||
char *dlid, *name;
|
||||
int r;
|
||||
|
||||
if (!(name = dm_build_dm_name(cmd->mem, lv->vg->name, lv->name, layer)))
|
||||
if (!(name = dm_build_dm_name(mem, lv->vg->name, lv->name, layer)))
|
||||
return_0;
|
||||
|
||||
if (!(dlid = build_dm_uuid(cmd->mem, lv, layer))) {
|
||||
if (!(dlid = build_dm_uuid(mem, lv, layer))) {
|
||||
r = 0;
|
||||
goto_out;
|
||||
}
|
||||
|
||||
log_debug_activation("Getting device info for %s [%s]", name, dlid);
|
||||
r = _info(cmd, dlid, with_open_count, with_read_ahead,
|
||||
r = _info(dlid, with_open_count, with_read_ahead,
|
||||
dminfo, read_ahead, seg_status);
|
||||
out:
|
||||
dm_pool_free(cmd->mem, name);
|
||||
dm_pool_free(mem, name);
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -774,11 +753,11 @@ static const struct dm_info *_cached_dm_info(struct dm_pool *mem,
|
||||
return_NULL;
|
||||
|
||||
if (!(dnode = dm_tree_find_node_by_uuid(dtree, dlid)))
|
||||
goto out;
|
||||
goto_out;
|
||||
|
||||
if (!(dinfo = dm_tree_node_get_info(dnode))) {
|
||||
log_warn("WARNING: Cannot get info from tree node for %s.",
|
||||
display_lvname(lv));
|
||||
log_error("Failed to get info from tree node for %s.",
|
||||
display_lvname(lv));
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -805,7 +784,7 @@ int lv_has_target_type(struct dm_pool *mem, const struct logical_volume *lv,
|
||||
if (!(dlid = build_dm_uuid(mem, lv, layer)))
|
||||
return_0;
|
||||
|
||||
if (!(dmt = _setup_task(NULL, dlid, 0, DM_DEVICE_STATUS, 0, 0, 0, 0)))
|
||||
if (!(dmt = _setup_task(NULL, dlid, 0, DM_DEVICE_STATUS, 0, 0, 0)))
|
||||
goto_bad;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
@@ -814,28 +793,13 @@ int lv_has_target_type(struct dm_pool *mem, const struct logical_volume *lv,
|
||||
if (!dm_task_get_info(dmt, &info) || !info.exists)
|
||||
goto_out;
|
||||
|
||||
/* If there is a preloaded table, use that in preference. */
|
||||
if (info.inactive_table) {
|
||||
dm_task_destroy(dmt);
|
||||
|
||||
if (!(dmt = _setup_task(NULL, dlid, 0, DM_DEVICE_STATUS, 0, 0, 0, 0)))
|
||||
goto_bad;
|
||||
|
||||
if (!dm_task_query_inactive_table(dmt))
|
||||
goto_out;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
goto_out;
|
||||
|
||||
if (!dm_task_get_info(dmt, &info) || !info.exists || !info.inactive_table)
|
||||
goto_out;
|
||||
}
|
||||
|
||||
do {
|
||||
next = dm_get_next_target(dmt, next, &start, &length,
|
||||
&type, ¶ms);
|
||||
if (type && !strncmp(type, target_type, strlen(target_type))) {
|
||||
r = 1;
|
||||
if (type && strncmp(type, target_type,
|
||||
strlen(target_type)) == 0) {
|
||||
if (info.live_table)
|
||||
r = 1;
|
||||
break;
|
||||
}
|
||||
} while (next);
|
||||
@@ -848,67 +812,6 @@ bad:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _thin_lv_has_device_id(struct dm_pool *mem, const struct logical_volume *lv,
|
||||
const char *layer, unsigned device_id)
|
||||
{
|
||||
char *dlid;
|
||||
struct dm_task *dmt;
|
||||
struct dm_info info;
|
||||
void *next = NULL;
|
||||
uint64_t start, length;
|
||||
char *type = NULL;
|
||||
char *params = NULL;
|
||||
unsigned id = ~0;
|
||||
|
||||
if (!(dlid = build_dm_uuid(mem, lv, layer)))
|
||||
return_0;
|
||||
|
||||
if (!(dmt = _setup_task(NULL, dlid, 0, DM_DEVICE_TABLE, 0, 0, 0, 1)))
|
||||
goto_bad;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
goto_out;
|
||||
|
||||
if (!dm_task_get_info(dmt, &info) || !info.exists)
|
||||
goto_out;
|
||||
|
||||
/* If there is a preloaded table, use that in preference. */
|
||||
if (info.inactive_table) {
|
||||
dm_task_destroy(dmt);
|
||||
|
||||
if (!(dmt = _setup_task(NULL, dlid, 0, DM_DEVICE_TABLE, 0, 0, 0, 1)))
|
||||
goto_bad;
|
||||
|
||||
if (!dm_task_query_inactive_table(dmt))
|
||||
goto_out;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
goto_out;
|
||||
|
||||
if (!dm_task_get_info(dmt, &info) || !info.exists || !info.inactive_table)
|
||||
goto_out;
|
||||
}
|
||||
|
||||
(void) dm_get_next_target(dmt, next, &start, &length, &type, ¶ms);
|
||||
|
||||
if (!type || strcmp(type, TARGET_NAME_THIN))
|
||||
goto_out;
|
||||
|
||||
if (!params || sscanf(params, "%*u:%*u %u", &id) != 1)
|
||||
goto_out;
|
||||
|
||||
log_debug_activation("%soaded thin volume %s with id %u is %smatching id %u.",
|
||||
info.inactive_table ? "Prel" : "L",
|
||||
display_lvname(lv), id,
|
||||
(device_id != id) ? "not " : "", device_id);
|
||||
out:
|
||||
dm_task_destroy(dmt);
|
||||
bad:
|
||||
dm_pool_free(mem, dlid);
|
||||
|
||||
return (device_id == id);
|
||||
}
|
||||
|
||||
int add_linear_area_to_dtree(struct dm_tree_node *node, uint64_t size, uint32_t extent_size, int use_linear_target, const char *vgname, const char *lvname)
|
||||
{
|
||||
uint32_t page_size;
|
||||
@@ -978,19 +881,22 @@ static int _percent_run(struct dev_manager *dm, const char *name,
|
||||
char *params = NULL;
|
||||
const struct dm_list *segh = lv ? &lv->segments : NULL;
|
||||
struct lv_segment *seg = NULL;
|
||||
struct segment_type *segtype;
|
||||
int first_time = 1;
|
||||
dm_percent_t percent = DM_PERCENT_INVALID;
|
||||
|
||||
uint64_t total_numerator = 0, total_denominator = 0;
|
||||
struct segment_type *segtype;
|
||||
|
||||
*overall_percent = percent;
|
||||
|
||||
if (!(segtype = get_segtype_from_string(dm->cmd, target_type)))
|
||||
if (!(dmt = _setup_task(name, dlid, event_nr,
|
||||
wait ? DM_DEVICE_WAITEVENT : DM_DEVICE_STATUS, 0, 0, 0)))
|
||||
return_0;
|
||||
|
||||
if (!(dmt = _setup_task(name, dlid, event_nr,
|
||||
wait ? DM_DEVICE_WAITEVENT : DM_DEVICE_STATUS, 0, 0, 0, 0)))
|
||||
return_0;
|
||||
/* No freeze on overfilled thin-pool, read existing slightly outdated data */
|
||||
if (lv && lv_is_thin_pool(lv) &&
|
||||
!dm_task_no_flush(dmt))
|
||||
log_warn("Can't set no_flush flag."); /* Non fatal */
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
goto_out;
|
||||
@@ -1017,6 +923,9 @@ static int _percent_run(struct dev_manager *dm, const char *name,
|
||||
if (!type || !params)
|
||||
continue;
|
||||
|
||||
if (!(segtype = get_segtype_from_string(dm->cmd, target_type)))
|
||||
continue;
|
||||
|
||||
if (strcmp(type, target_type)) {
|
||||
/* If kernel's type isn't an exact match is it compatible? */
|
||||
if (!segtype->ops->target_status_compatible ||
|
||||
@@ -1074,8 +983,7 @@ static int _percent(struct dev_manager *dm, const char *name, const char *dlid,
|
||||
if (_percent_run(dm, NULL, dlid, target_type, wait, lv, percent,
|
||||
event_nr, fail_if_percent_unsupported))
|
||||
return 1;
|
||||
else if (_original_uuid_format_check_required(dm->cmd) &&
|
||||
_percent_run(dm, NULL, dlid + sizeof(UUID_PREFIX) - 1,
|
||||
else if (_percent_run(dm, NULL, dlid + sizeof(UUID_PREFIX) - 1,
|
||||
target_type, wait, lv, percent,
|
||||
event_nr, fail_if_percent_unsupported))
|
||||
return 1;
|
||||
@@ -1106,7 +1014,7 @@ int dev_manager_transient(struct dev_manager *dm, const struct logical_volume *l
|
||||
if (!(dlid = build_dm_uuid(dm->mem, lv, layer)))
|
||||
return_0;
|
||||
|
||||
if (!(dmt = _setup_task(0, dlid, NULL, DM_DEVICE_STATUS, 0, 0, 0, 0)))
|
||||
if (!(dmt = _setup_task(0, dlid, NULL, DM_DEVICE_STATUS, 0, 0, 0)))
|
||||
return_0;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
@@ -1249,7 +1157,7 @@ int dev_manager_snapshot_percent(struct dev_manager *dm,
|
||||
/*
|
||||
* Try and get some info on this device.
|
||||
*/
|
||||
if (!_percent(dm, name, dlid, TARGET_NAME_SNAPSHOT, 0, NULL, percent,
|
||||
if (!_percent(dm, name, dlid, "snapshot", 0, NULL, percent,
|
||||
NULL, fail_if_percent_unsupported))
|
||||
return_0;
|
||||
|
||||
@@ -1302,7 +1210,7 @@ int dev_manager_raid_status(struct dev_manager *dm,
|
||||
if (!(dlid = build_dm_uuid(dm->mem, lv, layer)))
|
||||
return_0;
|
||||
|
||||
if (!(dmt = _setup_task(NULL, dlid, 0, DM_DEVICE_STATUS, 0, 0, 0, 0)))
|
||||
if (!(dmt = _setup_task(NULL, dlid, 0, DM_DEVICE_STATUS, 0, 0, 0)))
|
||||
return_0;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
@@ -1361,7 +1269,7 @@ int dev_manager_raid_message(struct dev_manager *dm,
|
||||
if (!(dlid = build_dm_uuid(dm->mem, lv, layer)))
|
||||
return_0;
|
||||
|
||||
if (!(dmt = _setup_task(NULL, dlid, 0, DM_DEVICE_TARGET_MSG, 0, 0, 0, 1)))
|
||||
if (!(dmt = _setup_task(NULL, dlid, 0, DM_DEVICE_TARGET_MSG, 0, 0, 0)))
|
||||
return_0;
|
||||
|
||||
if (!dm_task_set_message(dmt, msg))
|
||||
@@ -1396,7 +1304,7 @@ int dev_manager_cache_status(struct dev_manager *dm,
|
||||
if (!(*status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_cache))))
|
||||
return_0;
|
||||
|
||||
if (!(dmt = _setup_task(NULL, dlid, 0, DM_DEVICE_STATUS, 0, 0, 0, 0)))
|
||||
if (!(dmt = _setup_task(NULL, dlid, 0, DM_DEVICE_STATUS, 0, 0, 0)))
|
||||
return_0;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
@@ -1407,7 +1315,7 @@ int dev_manager_cache_status(struct dev_manager *dm,
|
||||
|
||||
dm_get_next_target(dmt, NULL, &start, &length, &type, ¶ms);
|
||||
|
||||
if (!type || strcmp(type, TARGET_NAME_CACHE)) {
|
||||
if (!type || strcmp(type, "cache")) {
|
||||
log_error("Expected cache segment type but got %s instead",
|
||||
type ? type : "NULL");
|
||||
goto out;
|
||||
@@ -1418,24 +1326,17 @@ int dev_manager_cache_status(struct dev_manager *dm,
|
||||
* ->target_percent() API is able to transfer only a single value.
|
||||
* Needs to be able to pass whole structure.
|
||||
*/
|
||||
if (!dm_get_status_cache(dm->mem, params, &c))
|
||||
if (!dm_get_status_cache(dm->mem, params, &((*status)->cache)))
|
||||
goto_out;
|
||||
|
||||
(*status)->cache = c;
|
||||
c = (*status)->cache;
|
||||
(*status)->mem = dm->mem; /* User has to destroy this mem pool later */
|
||||
if (c->fail || c->error) {
|
||||
(*status)->data_usage =
|
||||
(*status)->metadata_usage =
|
||||
(*status)->dirty_usage = DM_PERCENT_INVALID;
|
||||
} else {
|
||||
(*status)->data_usage = dm_make_percent(c->used_blocks,
|
||||
c->total_blocks);
|
||||
(*status)->metadata_usage = dm_make_percent(c->metadata_used_blocks,
|
||||
c->metadata_total_blocks);
|
||||
(*status)->dirty_usage = (c->used_blocks) ?
|
||||
dm_make_percent(c->dirty_blocks,
|
||||
c->used_blocks) : DM_PERCENT_0;
|
||||
}
|
||||
(*status)->data_usage = dm_make_percent(c->used_blocks,
|
||||
c->total_blocks);
|
||||
(*status)->metadata_usage = dm_make_percent(c->metadata_used_blocks,
|
||||
c->metadata_total_blocks);
|
||||
(*status)->dirty_usage = dm_make_percent(c->dirty_blocks,
|
||||
c->used_blocks);
|
||||
r = 1;
|
||||
out:
|
||||
dm_task_destroy(dmt);
|
||||
@@ -1446,7 +1347,7 @@ out:
|
||||
int dev_manager_thin_pool_status(struct dev_manager *dm,
|
||||
const struct logical_volume *lv,
|
||||
struct dm_status_thin_pool **status,
|
||||
int flush)
|
||||
int noflush)
|
||||
{
|
||||
const char *dlid;
|
||||
struct dm_task *dmt;
|
||||
@@ -1460,9 +1361,12 @@ int dev_manager_thin_pool_status(struct dev_manager *dm,
|
||||
if (!(dlid = build_dm_uuid(dm->mem, lv, lv_layer(lv))))
|
||||
return_0;
|
||||
|
||||
if (!(dmt = _setup_task(NULL, dlid, 0, DM_DEVICE_STATUS, 0, 0, 0, flush)))
|
||||
if (!(dmt = _setup_task(NULL, dlid, 0, DM_DEVICE_STATUS, 0, 0, 0)))
|
||||
return_0;
|
||||
|
||||
if (noflush && !dm_task_no_flush(dmt))
|
||||
log_warn("Can't set no_flush.");
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
goto_out;
|
||||
|
||||
@@ -1499,7 +1403,7 @@ int dev_manager_thin_pool_percent(struct dev_manager *dm,
|
||||
return_0;
|
||||
|
||||
log_debug_activation("Getting device status percentage for %s", name);
|
||||
if (!(_percent(dm, name, dlid, TARGET_NAME_THIN_POOL, 0,
|
||||
if (!(_percent(dm, name, dlid, "thin-pool", 0,
|
||||
(metadata) ? lv : NULL, percent, NULL, 1)))
|
||||
return_0;
|
||||
|
||||
@@ -1522,7 +1426,7 @@ int dev_manager_thin_percent(struct dev_manager *dm,
|
||||
return_0;
|
||||
|
||||
log_debug_activation("Getting device status percentage for %s", name);
|
||||
if (!(_percent(dm, name, dlid, TARGET_NAME_THIN, 0,
|
||||
if (!(_percent(dm, name, dlid, "thin", 0,
|
||||
(mapped) ? NULL : lv, percent, NULL, 1)))
|
||||
return_0;
|
||||
|
||||
@@ -1544,7 +1448,7 @@ int dev_manager_thin_device_id(struct dev_manager *dm,
|
||||
if (!(dlid = build_dm_uuid(dm->mem, lv, lv_layer(lv))))
|
||||
return_0;
|
||||
|
||||
if (!(dmt = _setup_task(NULL, dlid, 0, DM_DEVICE_TABLE, 0, 0, 0, 1)))
|
||||
if (!(dmt = _setup_task(NULL, dlid, 0, DM_DEVICE_TABLE, 0, 0, 0)))
|
||||
return_0;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
@@ -1560,7 +1464,7 @@ int dev_manager_thin_device_id(struct dev_manager *dm,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!target_type || strcmp(target_type, TARGET_NAME_THIN)) {
|
||||
if (!target_type || strcmp(target_type, "thin")) {
|
||||
log_error("Unexpected target type %s found for thin %s.",
|
||||
target_type, display_lvname(lv));
|
||||
goto out;
|
||||
@@ -1600,12 +1504,6 @@ static int _dev_manager_lv_rmnodes(const struct logical_volume *lv)
|
||||
return fs_del_lv(lv);
|
||||
}
|
||||
|
||||
static int _lv_has_mknode(const struct logical_volume *lv)
|
||||
{
|
||||
return (lv_is_visible(lv) &&
|
||||
(!lv_is_thin_pool(lv) || lv_is_new_thin_pool(lv)));
|
||||
}
|
||||
|
||||
int dev_manager_mknodes(const struct logical_volume *lv)
|
||||
{
|
||||
struct dm_info dminfo;
|
||||
@@ -1617,7 +1515,7 @@ int dev_manager_mknodes(const struct logical_volume *lv)
|
||||
|
||||
if ((r = _info_run(MKNODES, name, NULL, &dminfo, NULL, NULL, 0, 0, 0, 0))) {
|
||||
if (dminfo.exists) {
|
||||
if (_lv_has_mknode(lv))
|
||||
if (lv_is_visible(lv))
|
||||
r = _dev_manager_lv_mknodes(lv);
|
||||
} else
|
||||
r = _dev_manager_lv_rmnodes(lv);
|
||||
@@ -1757,7 +1655,7 @@ static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
return_0;
|
||||
|
||||
log_debug_activation("Getting device info for %s [%s]", name, dlid);
|
||||
if (!_info(dm->cmd, dlid, 1, 0, &info, NULL, NULL)) {
|
||||
if (!_info(dlid, 1, 0, &info, NULL, NULL)) {
|
||||
log_error("Failed to get info for %s [%s].", name, dlid);
|
||||
return 0;
|
||||
}
|
||||
@@ -1770,7 +1668,7 @@ static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
/*
|
||||
* FIXME compare info.major with lv->major if multiple major support
|
||||
*/
|
||||
if (info.exists && ((int) info.minor != lv->minor)) {
|
||||
if (info.exists && (info.minor != lv->minor)) {
|
||||
log_error("Volume %s (%" PRIu32 ":%" PRIu32")"
|
||||
" differs from already active device "
|
||||
"(%" PRIu32 ":%" PRIu32")",
|
||||
@@ -1941,22 +1839,22 @@ static int _pool_callback(struct dm_tree_node *node,
|
||||
return 0;
|
||||
}
|
||||
/* let's assume there is no problem to read 64 bytes */
|
||||
if (read(fd, buf, sizeof(buf)) < (int)sizeof(buf)) {
|
||||
if (read(fd, buf, sizeof(buf)) < sizeof(buf)) {
|
||||
log_sys_error("read", argv[args]);
|
||||
if (close(fd))
|
||||
log_sys_error("close", argv[args]);
|
||||
return 0;
|
||||
}
|
||||
for (ret = 0; ret < (int) DM_ARRAY_SIZE(buf); ++ret)
|
||||
for (ret = 0; ret < DM_ARRAY_SIZE(buf); ++ret)
|
||||
if (buf[ret])
|
||||
break;
|
||||
|
||||
if (close(fd))
|
||||
log_sys_error("close", argv[args]);
|
||||
|
||||
if (ret == (int) DM_ARRAY_SIZE(buf)) {
|
||||
log_debug_activation("%s skipped, detect empty disk header on %s.",
|
||||
argv[0], argv[args]);
|
||||
if (ret == DM_ARRAY_SIZE(buf)) {
|
||||
log_debug("%s skipped, detect empty disk header on %s.",
|
||||
argv[0], argv[args]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -2016,7 +1914,7 @@ static int _pool_register_callback(struct dev_manager *dm,
|
||||
data->global = "thin";
|
||||
} else if (lv_is_cache(lv)) { /* cache pool */
|
||||
data->pool_lv = first_seg(lv)->pool_lv;
|
||||
data->skip_zero = 1; /* cheap read-error detection */
|
||||
data->skip_zero = dm->activation;
|
||||
data->exec = global_cache_check_executable_CFG;
|
||||
data->opts = global_cache_check_options_CFG;
|
||||
data->global = "cache";
|
||||
@@ -2161,7 +2059,6 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
dm_list_iterate(snh, &lv->snapshot_segs)
|
||||
if (!_add_lv_to_dtree(dm, dtree, dm_list_struct_base(snh, struct lv_segment, origin_list)->cow, 0))
|
||||
return_0;
|
||||
|
||||
if (dm->activation && !origin_only && lv_is_merging_origin(lv) &&
|
||||
!_add_lv_to_dtree(dm, dtree, find_snapshot(lv)->lv, 1))
|
||||
return_0;
|
||||
@@ -2214,7 +2111,7 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
(!dm->track_pending_delete || !lv_is_cache(lv)) &&
|
||||
!_add_lv_to_dtree(dm, dtree, seg_lv(seg, s), 0))
|
||||
return_0;
|
||||
if (seg_is_raid_with_meta(seg) && seg->meta_areas && seg_metalv(seg, s) &&
|
||||
if (seg_is_raid(seg) &&
|
||||
!_add_lv_to_dtree(dm, dtree, seg_metalv(seg, s), 0))
|
||||
return_0;
|
||||
}
|
||||
@@ -2282,7 +2179,7 @@ static char *_add_error_device(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
return_NULL;
|
||||
|
||||
log_debug_activation("Getting device info for %s [%s]", name, dlid);
|
||||
if (!_info(dm->cmd, dlid, 1, 0, &info, NULL, NULL)) {
|
||||
if (!_info(dlid, 1, 0, &info, NULL, NULL)) {
|
||||
log_error("Failed to get info for %s [%s].", name, dlid);
|
||||
return 0;
|
||||
}
|
||||
@@ -2311,7 +2208,7 @@ static int _add_error_area(struct dev_manager *dm, struct dm_tree_node *node,
|
||||
char *dlid;
|
||||
uint64_t extent_size = seg->lv->vg->extent_size;
|
||||
|
||||
if (!strcmp(dm->cmd->stripe_filler, TARGET_NAME_ERROR)) {
|
||||
if (!strcmp(dm->cmd->stripe_filler, "error")) {
|
||||
/*
|
||||
* FIXME, the tree pointer is first field of dm_tree_node, but
|
||||
* we don't have the struct definition available.
|
||||
@@ -2386,13 +2283,9 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
|
||||
return_0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (seg->meta_areas && seg_metalv(seg, s)) {
|
||||
if (!(dlid = build_dm_uuid(dm->mem, seg_metalv(seg, s), NULL)))
|
||||
return_0;
|
||||
if (!dm_tree_node_add_target_area(node, NULL, dlid, extent_size * seg_metale(seg, s)))
|
||||
return_0;
|
||||
} else if (!dm_tree_node_add_null_area(node, 0))
|
||||
if (!(dlid = build_dm_uuid(dm->mem, seg_metalv(seg, s), NULL)))
|
||||
return_0;
|
||||
if (!dm_tree_node_add_target_area(node, NULL, dlid, extent_size * seg_metale(seg, s)))
|
||||
return_0;
|
||||
|
||||
if (!(dlid = build_dm_uuid(dm->mem, seg_lv(seg, s), NULL)))
|
||||
@@ -2720,7 +2613,7 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
|
||||
!_add_new_lv_to_dtree(dm, dtree, seg_lv(seg, s),
|
||||
laopts, NULL))
|
||||
return_0;
|
||||
if (seg_is_raid_with_meta(seg) && seg->meta_areas && seg_metalv(seg, s) &&
|
||||
if (seg_is_raid(seg) &&
|
||||
!_add_new_lv_to_dtree(dm, dtree, seg_metalv(seg, s),
|
||||
laopts, NULL))
|
||||
return_0;
|
||||
@@ -2753,7 +2646,6 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
uint32_t read_ahead = lv->read_ahead;
|
||||
uint32_t read_ahead_flags = UINT32_C(0);
|
||||
int save_pending_delete = dm->track_pending_delete;
|
||||
int merge_in_progress = 0;
|
||||
|
||||
/* LV with pending delete is never put new into a table */
|
||||
if (lv_is_pending_delete(lv) && !_cached_dm_info(dm->mem, dtree, lv, NULL))
|
||||
@@ -2774,51 +2666,23 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
if (!layer && lv_is_merging_origin(lv)) {
|
||||
seg = find_snapshot(lv);
|
||||
/*
|
||||
* Prevent merge if merge isn't currently possible:
|
||||
* Clear merge attributes if merge isn't currently possible:
|
||||
* either origin or merging snapshot are open
|
||||
* - for old snaps use "snapshot-merge" if it is already in use
|
||||
* - but use "snapshot-merge" if it is already in use
|
||||
* - open_count is always retrieved (as of dm-ioctl 4.7.0)
|
||||
* so just use the tree's existing nodes' info
|
||||
*/
|
||||
if ((dinfo = _cached_dm_info(dm->mem, dtree, lv, NULL))) {
|
||||
/* Merging origin LV is present, check if mergins is already running. */
|
||||
if ((seg_is_thin_volume(seg) && _thin_lv_has_device_id(dm->mem, lv, NULL, seg->device_id)) ||
|
||||
(!seg_is_thin_volume(seg) && lv_has_target_type(dm->mem, lv, NULL, TARGET_NAME_SNAPSHOT_MERGE))) {
|
||||
log_debug_activation("Merging of snapshot volume %s to origin %s is in progress.",
|
||||
display_lvname(seg->lv), display_lvname(seg->lv));
|
||||
merge_in_progress = 1; /* Merge is already running */
|
||||
} /* Merge is not yet running, so check if it can be started */
|
||||
else if (laopts->resuming) {
|
||||
log_debug_activation("Postponing pending snapshot merge for origin %s, "
|
||||
"merge was not started before suspend.",
|
||||
display_lvname(lv));
|
||||
laopts->no_merging = 1; /* Cannot be reloaded in suspend */
|
||||
} /* Non-resuming merge requires origin to be unused */
|
||||
else if (dinfo->open_count) {
|
||||
log_debug_activation("Postponing pending snapshot merge for origin %s, "
|
||||
"origin volume is opened.",
|
||||
display_lvname(lv));
|
||||
/* An activating merging origin won't have a node in the tree yet */
|
||||
if (((dinfo = _cached_dm_info(dm->mem, dtree, lv, NULL)) &&
|
||||
dinfo->open_count) ||
|
||||
((dinfo = _cached_dm_info(dm->mem, dtree,
|
||||
seg_is_thin_volume(seg) ?
|
||||
seg->lv : seg->cow, NULL)) &&
|
||||
dinfo->open_count)) {
|
||||
if (seg_is_thin_volume(seg) ||
|
||||
/* FIXME Is there anything simpler to check for instead? */
|
||||
!lv_has_target_type(dm->mem, lv, NULL, "snapshot-merge"))
|
||||
laopts->no_merging = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* If merge would be still undecided, look as snapshot */
|
||||
if (!merge_in_progress && !laopts->no_merging &&
|
||||
(dinfo = _cached_dm_info(dm->mem, dtree,
|
||||
seg_is_thin_volume(seg) ?
|
||||
seg->lv : seg->cow, NULL))) {
|
||||
if (seg_is_thin_volume(seg)) {
|
||||
/* Active thin snapshot prevents merge */
|
||||
log_debug_activation("Postponing pending snapshot merge for origin volume %s, "
|
||||
"merging thin snapshot volume %s is active.",
|
||||
display_lvname(lv), display_lvname(seg->lv));
|
||||
laopts->no_merging = 1;
|
||||
} else if (dinfo->open_count) {
|
||||
log_debug_activation("Postponing pending snapshot merge for origin volume %s, "
|
||||
"merging snapshot volume %s is opened.",
|
||||
display_lvname(lv), display_lvname(seg->lv));
|
||||
laopts->no_merging = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3000,7 +2864,7 @@ static int _create_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root
|
||||
r = 0;
|
||||
continue;
|
||||
}
|
||||
if (_lv_has_mknode(lvlayer->lv)) {
|
||||
if (lv_is_visible(lvlayer->lv)) {
|
||||
if (!_dev_manager_lv_mknodes(lvlayer->lv))
|
||||
r = 0;
|
||||
continue;
|
||||
@@ -3116,7 +2980,6 @@ static int _tree_action(struct dev_manager *dm, const struct logical_volume *lv,
|
||||
/* Some targets may build bigger tree for activation */
|
||||
dm->activation = ((action == PRELOAD) || (action == ACTIVATE));
|
||||
dm->suspend = (action == SUSPEND_WITH_LOCKFS) || (action == SUSPEND);
|
||||
|
||||
if (!(dtree = _create_partial_dtree(dm, lv, laopts->origin_only)))
|
||||
return_0;
|
||||
|
||||
@@ -3152,7 +3015,7 @@ static int _tree_action(struct dev_manager *dm, const struct logical_volume *lv,
|
||||
break;
|
||||
case SUSPEND:
|
||||
dm_tree_skip_lockfs(root);
|
||||
if (!dm->flush_required)
|
||||
if (!dm->flush_required && !lv_is_pvmove(lv))
|
||||
dm_tree_use_no_flush_suspend(root);
|
||||
/* Fall through */
|
||||
case SUSPEND_WITH_LOCKFS:
|
||||
@@ -3171,15 +3034,14 @@ static int _tree_action(struct dev_manager *dm, const struct logical_volume *lv,
|
||||
if (!dm_tree_preload_children(root, dlid, DLID_SIZE))
|
||||
goto_out;
|
||||
|
||||
//if (action == PRELOAD) { log_debug("SLEEP"); sleep(7); }
|
||||
|
||||
if ((dm_tree_node_size_changed(root) < 0))
|
||||
dm->flush_required = 1;
|
||||
|
||||
/* Currently keep the code require flush for any
|
||||
* non 'thin pool/volume' and size increase */
|
||||
else if (!lv_is_thin_volume(lv) &&
|
||||
!lv_is_thin_pool(lv) &&
|
||||
dm_tree_node_size_changed(root))
|
||||
* non 'thin pool/volume, mirror' or with any size change */
|
||||
if (!lv_is_thin_volume(lv) &&
|
||||
!lv_is_thin_pool(lv) &&
|
||||
(!lv_is_mirror(lv) || dm_tree_node_size_changed(root)))
|
||||
dm->flush_required = 1;
|
||||
|
||||
if (action == ACTIVATE) {
|
||||
@@ -3224,8 +3086,6 @@ int dev_manager_activate(struct dev_manager *dm, const struct logical_volume *lv
|
||||
int dev_manager_preload(struct dev_manager *dm, const struct logical_volume *lv,
|
||||
struct lv_activate_opts *laopts, int *flush_required)
|
||||
{
|
||||
dm->flush_required = *flush_required;
|
||||
|
||||
if (!_tree_action(dm, lv, laopts, PRELOAD))
|
||||
return_0;
|
||||
|
||||
|
@@ -45,12 +45,11 @@ void dev_manager_exit(void);
|
||||
* (eg, an origin is created before its snapshot, but is not
|
||||
* unsuspended until the snapshot is also created.)
|
||||
*/
|
||||
int dev_manager_info(struct cmd_context *cmd, const struct logical_volume *lv,
|
||||
int dev_manager_info(struct dm_pool *mem, const struct logical_volume *lv,
|
||||
const char *layer,
|
||||
int with_open_count, int with_read_ahead,
|
||||
struct dm_info *dminfo, uint32_t *read_ahead,
|
||||
struct lv_seg_status *seg_status);
|
||||
|
||||
int dev_manager_snapshot_percent(struct dev_manager *dm,
|
||||
const struct logical_volume *lv,
|
||||
dm_percent_t *percent);
|
||||
@@ -69,7 +68,7 @@ int dev_manager_cache_status(struct dev_manager *dm,
|
||||
int dev_manager_thin_pool_status(struct dev_manager *dm,
|
||||
const struct logical_volume *lv,
|
||||
struct dm_status_thin_pool **status,
|
||||
int flush);
|
||||
int noflush);
|
||||
int dev_manager_thin_pool_percent(struct dev_manager *dm,
|
||||
const struct logical_volume *lv,
|
||||
int metadata, dm_percent_t *percent);
|
||||
|
950
lib/cache/lvmcache.c
vendored
950
lib/cache/lvmcache.c
vendored
File diff suppressed because it is too large
Load Diff
18
lib/cache/lvmcache.h
vendored
18
lib/cache/lvmcache.h
vendored
@@ -102,16 +102,15 @@ int lvmcache_vginfo_holders_dec_and_test_for_zero(struct lvmcache_vginfo *vginfo
|
||||
struct lvmcache_vginfo *lvmcache_vginfo_from_vgname(const char *vgname,
|
||||
const char *vgid);
|
||||
struct lvmcache_vginfo *lvmcache_vginfo_from_vgid(const char *vgid);
|
||||
struct lvmcache_info *lvmcache_info_from_pvid(const char *pvid, struct device *dev, int valid_only);
|
||||
struct lvmcache_info *lvmcache_info_from_pvid(const char *pvid, int valid_only);
|
||||
const char *lvmcache_vgname_from_vgid(struct dm_pool *mem, const char *vgid);
|
||||
const char *lvmcache_vgid_from_vgname(struct cmd_context *cmd, const char *vgname);
|
||||
struct device *lvmcache_device_from_pvid(struct cmd_context *cmd, const struct id *pvid,
|
||||
unsigned *scan_done_once, uint64_t *label_sector);
|
||||
const char *lvmcache_pvid_from_devname(struct cmd_context *cmd,
|
||||
const char *devname);
|
||||
const char *dev_name);
|
||||
char *lvmcache_vgname_from_pvid(struct cmd_context *cmd, const char *pvid);
|
||||
const char *lvmcache_vgname_from_info(struct lvmcache_info *info);
|
||||
const struct format_type *lvmcache_fmt_from_info(struct lvmcache_info *info);
|
||||
int lvmcache_vgs_locked(void);
|
||||
int lvmcache_vgname_is_locked(const char *vgname);
|
||||
|
||||
@@ -194,11 +193,12 @@ unsigned lvmcache_mda_count(struct lvmcache_info *info);
|
||||
int lvmcache_vgid_is_cached(const char *vgid);
|
||||
uint64_t lvmcache_smallest_mda_size(struct lvmcache_info *info);
|
||||
|
||||
void lvmcache_replace_dev(struct cmd_context *cmd, struct physical_volume *pv,
|
||||
struct device *dev);
|
||||
|
||||
int lvmcache_found_duplicate_pvs(void);
|
||||
|
||||
int lvmcache_get_unused_duplicate_devs(struct cmd_context *cmd, struct dm_list *head);
|
||||
|
||||
int vg_has_duplicate_pvs(struct volume_group *vg);
|
||||
void lvmcache_set_preferred_duplicates(const char *vgid);
|
||||
|
||||
int lvmcache_contains_lock_type_sanlock(struct cmd_context *cmd);
|
||||
|
||||
@@ -209,10 +209,4 @@ int lvmcache_vg_is_foreign(struct cmd_context *cmd, const char *vgname, const ch
|
||||
|
||||
void lvmcache_lock_ordering(int enable);
|
||||
|
||||
int lvmcache_dev_is_unchosen_duplicate(struct device *dev);
|
||||
|
||||
void lvmcache_remove_unchosen_duplicate(struct device *dev);
|
||||
|
||||
int lvmcache_pvid_in_unchosen_duplicates(const char *pvid);
|
||||
|
||||
#endif
|
||||
|
1816
lib/cache/lvmetad.c
vendored
1816
lib/cache/lvmetad.c
vendored
File diff suppressed because it is too large
Load Diff
103
lib/cache/lvmetad.h
vendored
103
lib/cache/lvmetad.h
vendored
@@ -28,35 +28,54 @@ typedef int (*activation_handler) (struct cmd_context *cmd,
|
||||
enum activation_change activate);
|
||||
|
||||
#ifdef LVMETAD_SUPPORT
|
||||
/*
|
||||
* Sets up a global handle for our process.
|
||||
*/
|
||||
void lvmetad_init(struct cmd_context *);
|
||||
|
||||
/*
|
||||
* lvmetad_connect: connect to lvmetad
|
||||
* lvmetad_disconnect: disconnect from lvmetad
|
||||
* lvmetad_make_unused: disconnect from lvmetad and refresh cmd filter
|
||||
* lvmetad_used: check if lvmetad is being used (i.e. is connected)
|
||||
* Override the use of lvmetad for retrieving scan results and metadata.
|
||||
*/
|
||||
int lvmetad_connect(struct cmd_context *cmd);
|
||||
void lvmetad_disconnect(void);
|
||||
void lvmetad_make_unused(struct cmd_context *cmd);
|
||||
int lvmetad_used(void);
|
||||
|
||||
void lvmetad_set_active(struct cmd_context *, int);
|
||||
|
||||
/*
|
||||
* Configure the socket that lvmetad_init will use to connect to the daemon.
|
||||
*/
|
||||
void lvmetad_set_socket(const char *);
|
||||
|
||||
/*
|
||||
* Check whether lvmetad is used.
|
||||
*/
|
||||
int lvmetad_used(void);
|
||||
|
||||
/*
|
||||
* Check if lvmetad socket is present (either the one set by lvmetad_set_socket
|
||||
* or the default one if not set).
|
||||
* or the default one if not set). For example, this may be used before calling
|
||||
* lvmetad_active() check that does connect to the socket - this would produce
|
||||
* various connection errors if the socket is not present.
|
||||
*/
|
||||
int lvmetad_socket_present(void);
|
||||
|
||||
/*
|
||||
* Check if lvmetad pidfile is present, indicating that the lvmetad
|
||||
* process is running or not.
|
||||
* Check whether lvmetad is active (where active means both that it is running
|
||||
* and that we have a working connection with it). It opens new connection
|
||||
* with lvmetad in the process when lvmetad is supposed to be used and the
|
||||
* connection is not open yet.
|
||||
*/
|
||||
int lvmetad_pidfile_present(void);
|
||||
int lvmetad_active(void);
|
||||
|
||||
/*
|
||||
* Connect to lvmetad unless the connection is already open or lvmetad is
|
||||
* not configured to be used. If we fail to connect, print a warning.
|
||||
*/
|
||||
void lvmetad_connect_or_warn(void);
|
||||
|
||||
/*
|
||||
* Drop connection to lvmetad. A subsequent lvmetad_connect_or_warn or
|
||||
* lvmetad_active will re-establish the connection (possibly at a
|
||||
* different socket path).
|
||||
*/
|
||||
void lvmetad_disconnect(void);
|
||||
|
||||
/*
|
||||
* Set the "lvmetad validity token" (currently only consists of the lvmetad
|
||||
@@ -78,16 +97,14 @@ void lvmetad_release_token(void);
|
||||
* lvmetad_vg_commit. The request is validated immediately and lvmetad_vg_commit
|
||||
* only constitutes a pointer update.
|
||||
*/
|
||||
int lvmetad_vg_update_pending(struct volume_group *vg);
|
||||
int lvmetad_vg_update_finish(struct volume_group *vg);
|
||||
int lvmetad_vg_update(struct volume_group *vg);
|
||||
|
||||
/*
|
||||
* Inform lvmetad that a VG has been removed. This is not entirely safe, but is
|
||||
* only needed during vgremove, which does not wipe PV labels and therefore
|
||||
* cannot mark the PVs as gone.
|
||||
*/
|
||||
int lvmetad_vg_remove_pending(struct volume_group *vg);
|
||||
int lvmetad_vg_remove_finish(struct volume_group *vg);
|
||||
int lvmetad_vg_remove(struct volume_group *vg);
|
||||
|
||||
/*
|
||||
* Notify lvmetad that a PV has been found. It is not an error if the PV is
|
||||
@@ -97,17 +114,15 @@ int lvmetad_vg_remove_finish(struct volume_group *vg);
|
||||
* number on the cached and on the discovered PV match but the metadata content
|
||||
* does not.
|
||||
*/
|
||||
int lvmetad_pv_found(struct cmd_context *cmd, const struct id *pvid, struct device *dev,
|
||||
int lvmetad_pv_found(const struct id *pvid, struct device *dev,
|
||||
const struct format_type *fmt, uint64_t label_sector,
|
||||
struct volume_group *vg,
|
||||
struct dm_list *found_vgnames,
|
||||
struct dm_list *changed_vgnames);
|
||||
struct volume_group *vg, activation_handler handler);
|
||||
|
||||
/*
|
||||
* Inform the daemon that the device no longer exists.
|
||||
*/
|
||||
int lvmetad_pv_gone(dev_t devno, const char *pv_name);
|
||||
int lvmetad_pv_gone_by_dev(struct device *dev);
|
||||
int lvmetad_pv_gone(dev_t devno, const char *pv_name, activation_handler handler);
|
||||
int lvmetad_pv_gone_by_dev(struct device *dev, activation_handler handler);
|
||||
|
||||
/*
|
||||
* Request a list of all PVs available to lvmetad. If requested, this will also
|
||||
@@ -146,55 +161,45 @@ struct volume_group *lvmetad_vg_lookup(struct cmd_context *cmd,
|
||||
* Scan a single device and update lvmetad with the result(s).
|
||||
*/
|
||||
int lvmetad_pvscan_single(struct cmd_context *cmd, struct device *dev,
|
||||
struct dm_list *found_vgnames,
|
||||
struct dm_list *changed_vgnames);
|
||||
activation_handler handler, int ignore_obsolete);
|
||||
|
||||
int lvmetad_pvscan_all_devs(struct cmd_context *cmd, int do_wait);
|
||||
int lvmetad_pvscan_all_devs(struct cmd_context *cmd, activation_handler handler);
|
||||
int lvmetad_pvscan_foreign_vgs(struct cmd_context *cmd, activation_handler handler);
|
||||
|
||||
int lvmetad_vg_clear_outdated_pvs(struct volume_group *vg);
|
||||
void lvmetad_validate_global_cache(struct cmd_context *cmd, int force);
|
||||
int lvmetad_token_matches(struct cmd_context *cmd);
|
||||
|
||||
int lvmetad_vg_is_foreign(struct cmd_context *cmd, const char *vgname, const char *vgid);
|
||||
|
||||
int lvmetad_is_disabled(struct cmd_context *cmd, const char **reason);
|
||||
void lvmetad_set_disabled(struct cmd_context *cmd, const char *reason);
|
||||
void lvmetad_clear_disabled(struct cmd_context *cmd);
|
||||
|
||||
# else /* LVMETAD_SUPPORT */
|
||||
|
||||
# define lvmetad_init(cmd) do { } while (0)
|
||||
# define lvmetad_disconnect() do { } while (0)
|
||||
# define lvmetad_connect(cmd) (0)
|
||||
# define lvmetad_make_unused(cmd) do { } while (0)
|
||||
# define lvmetad_used() (0)
|
||||
# define lvmetad_set_active(cmd, a) do { } while (0)
|
||||
# define lvmetad_set_socket(a) do { } while (0)
|
||||
# define lvmetad_used() (0)
|
||||
# define lvmetad_socket_present() (0)
|
||||
# define lvmetad_pidfile_present() (0)
|
||||
# define lvmetad_active() (0)
|
||||
# define lvmetad_connect_or_warn() do { } while (0)
|
||||
# define lvmetad_set_token(a) do { } while (0)
|
||||
# define lvmetad_release_token() do { } while (0)
|
||||
# define lvmetad_vg_update(vg) (1)
|
||||
# define lvmetad_vg_update_pending(vg) (1)
|
||||
# define lvmetad_vg_update_finish(vg) (1)
|
||||
# define lvmetad_vg_remove_pending(vg) (1)
|
||||
# define lvmetad_vg_remove_finish(vg) (1)
|
||||
# define lvmetad_pv_found(cmd, pvid, dev, fmt, label_sector, vg, found_vgnames, changed_vgnames) (1)
|
||||
# define lvmetad_pv_gone(devno, pv_name) (1)
|
||||
# define lvmetad_pv_gone_by_dev(dev) (1)
|
||||
# define lvmetad_vg_remove(vg) (1)
|
||||
# define lvmetad_pv_found(pvid, dev, fmt, label_sector, vg, handler) (1)
|
||||
# define lvmetad_pv_gone(devno, pv_name, handler) (1)
|
||||
# define lvmetad_pv_gone_by_dev(dev, handler) (1)
|
||||
# define lvmetad_pv_list_to_lvmcache(cmd) (1)
|
||||
# define lvmetad_pv_lookup(cmd, pvid, found) (0)
|
||||
# define lvmetad_pv_lookup_by_dev(cmd, dev, found) (0)
|
||||
# define lvmetad_vg_list_to_lvmcache(cmd) (1)
|
||||
# define lvmetad_get_vgnameids(cmd, vgnameids) do { } while (0)
|
||||
# define lvmetad_vg_lookup(cmd, vgname, vgid) (NULL)
|
||||
# define lvmetad_pvscan_single(cmd, dev, found_vgnames, changed_vgnames) (0)
|
||||
# define lvmetad_pvscan_all_devs(cmd, do_wait) (0)
|
||||
# define lvmetad_vg_clear_outdated_pvs(vg) do { } while (0)
|
||||
# define lvmetad_pvscan_single(cmd, dev, handler, ignore_obsolete) (0)
|
||||
# define lvmetad_pvscan_all_devs(cmd, handler) (0)
|
||||
# define lvmetad_pvscan_foreign_vgs(cmd, handler) (0)
|
||||
# define lvmetad_vg_clear_outdated_pvs(vg) (1)
|
||||
# define lvmetad_validate_global_cache(cmd, force) do { } while (0)
|
||||
# define lvmetad_vg_is_foreign(cmd, vgname, vgid) (0)
|
||||
# define lvmetad_token_matches(cmd) (1)
|
||||
# define lvmetad_is_disabled(cmd, reason) (0)
|
||||
# define lvmetad_set_disabled(cmd, reason) do { } while (0)
|
||||
# define lvmetad_clear_disabled(cmd) do { } while (0)
|
||||
|
||||
# endif /* LVMETAD_SUPPORT */
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2016 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2013-2014 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@@ -26,8 +26,6 @@
|
||||
#include "defaults.h"
|
||||
|
||||
static const char _cache_module[] = "cache";
|
||||
#define CACHE_POLICY_WHEN_MISSING "mq"
|
||||
#define CACHE_MODE_WHEN_MISSING CACHE_MODE_WRITETHROUGH
|
||||
|
||||
/* TODO: using static field here, maybe should be a part of segment_type */
|
||||
static unsigned _feature_mask;
|
||||
@@ -43,21 +41,24 @@ static unsigned _feature_mask;
|
||||
*
|
||||
* Needs both segments cache and cache_pool to be loaded.
|
||||
*/
|
||||
static void _fix_missing_defaults(struct lv_segment *cpool_seg)
|
||||
static int _fix_missing_defaults(struct lv_segment *cpool_seg)
|
||||
{
|
||||
if (!cpool_seg->policy_name) {
|
||||
cpool_seg->policy_name = CACHE_POLICY_WHEN_MISSING;
|
||||
log_verbose("Cache pool %s is missing cache policy, using %s.",
|
||||
display_lvname(cpool_seg->lv),
|
||||
cpool_seg->policy_name = "mq";
|
||||
log_verbose("Cache is missing cache policy, using %s.",
|
||||
cpool_seg->policy_name);
|
||||
}
|
||||
|
||||
if (cpool_seg->cache_mode == CACHE_MODE_UNDEFINED) {
|
||||
cpool_seg->cache_mode = CACHE_MODE_WHEN_MISSING;
|
||||
log_verbose("Cache pool %s is missing cache mode, using %s.",
|
||||
display_lvname(cpool_seg->lv),
|
||||
if (!cache_mode_is_set(cpool_seg)) {
|
||||
if (!cache_set_mode(cpool_seg, "writethrough")) {
|
||||
log_error(INTERNAL_ERROR "Failed to writethrough cache mode.");
|
||||
return 0;
|
||||
}
|
||||
log_verbose("Cache is missing cache mode, using %s.",
|
||||
get_cache_mode_name(cpool_seg));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _cache_pool_text_import(struct lv_segment *seg,
|
||||
@@ -96,7 +97,7 @@ static int _cache_pool_text_import(struct lv_segment *seg,
|
||||
if (dm_config_has_node(sn, "cache_mode")) {
|
||||
if (!(str = dm_config_find_str(sn, "cache_mode", NULL)))
|
||||
return SEG_LOG_ERROR("cache_mode must be a string in");
|
||||
if (!set_cache_mode(&seg->cache_mode, str))
|
||||
if (!cache_set_mode(seg, str))
|
||||
return SEG_LOG_ERROR("Unknown cache_mode in");
|
||||
}
|
||||
|
||||
@@ -140,9 +141,9 @@ static int _cache_pool_text_import(struct lv_segment *seg,
|
||||
if (!attach_pool_metadata_lv(seg, meta_lv))
|
||||
return_0;
|
||||
|
||||
/* when cache pool is used, we require policy and mode to be defined */
|
||||
if (!dm_list_empty(&seg->lv->segs_using_this_lv))
|
||||
_fix_missing_defaults(seg);
|
||||
if (!dm_list_empty(&seg->lv->segs_using_this_lv) &&
|
||||
!_fix_missing_defaults(seg))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -169,7 +170,7 @@ static int _cache_pool_text_export(const struct lv_segment *seg,
|
||||
* but not worth to break backward compatibility, by shifting
|
||||
* content to cache segment
|
||||
*/
|
||||
if (seg->cache_mode != CACHE_MODE_UNDEFINED) {
|
||||
if (cache_mode_is_set(seg)) {
|
||||
if (!(cache_mode = get_cache_mode_name(seg)))
|
||||
return_0;
|
||||
outf(f, "cache_mode = \"%s\"", cache_mode);
|
||||
@@ -207,16 +208,11 @@ static int _target_present(struct cmd_context *cmd,
|
||||
uint32_t maj;
|
||||
uint32_t min;
|
||||
unsigned cache_feature;
|
||||
unsigned cache_alias;
|
||||
const char feature[12];
|
||||
const char module[12]; /* check dm-%s */
|
||||
const char *aliasing;
|
||||
} _features[] = {
|
||||
/* Assumption: cache >=1.9 always aliases MQ policy */
|
||||
{ 1, 9, CACHE_FEATURE_POLICY_SMQ, CACHE_FEATURE_POLICY_MQ, "policy_smq", "cache-smq",
|
||||
" and aliases cache-mq" },
|
||||
{ 1, 8, CACHE_FEATURE_POLICY_SMQ, 0, "policy_smq", "cache-smq" },
|
||||
{ 1, 3, CACHE_FEATURE_POLICY_MQ, 0, "policy_mq", "cache-mq" },
|
||||
{ 1, 3, CACHE_FEATURE_POLICY_MQ, "policy_mq", "cache-mq" },
|
||||
{ 1, 8, CACHE_FEATURE_POLICY_SMQ, "policy_smq", "cache-smq" },
|
||||
};
|
||||
static const char _lvmconf[] = "global/cache_disabled_features";
|
||||
static unsigned _attrs = 0;
|
||||
@@ -234,8 +230,10 @@ static int _target_present(struct cmd_context *cmd,
|
||||
if (!_cache_checked) {
|
||||
_cache_checked = 1;
|
||||
|
||||
if (!(_cache_present = target_present_version(cmd, TARGET_NAME_CACHE, 1,
|
||||
&maj, &min, &patchlevel)))
|
||||
if (!(_cache_present = target_present(cmd, "cache", 1)))
|
||||
return 0;
|
||||
|
||||
if (!target_version("cache", &maj, &min, &patchlevel))
|
||||
return_0;
|
||||
|
||||
if ((maj < 1) ||
|
||||
@@ -247,17 +245,13 @@ static int _target_present(struct cmd_context *cmd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < DM_ARRAY_SIZE(_features); ++i) {
|
||||
if (_attrs & _features[i].cache_feature)
|
||||
continue; /* already present */
|
||||
if (((maj > _features[i].maj) ||
|
||||
(maj == _features[i].maj && min >= _features[i].min)) &&
|
||||
module_present(cmd, _features[i].module)) {
|
||||
log_debug_activation("Cache policy %s is available%s.",
|
||||
_features[i].module,
|
||||
_features[i].aliasing ? : "");
|
||||
_attrs |= (_features[i].cache_feature | _features[i].cache_alias);
|
||||
} else if (!_features[i].cache_alias)
|
||||
(!_features[i].module[0] || module_present(cmd, _features[i].module)))
|
||||
_attrs |= _features[i].cache_feature;
|
||||
else
|
||||
log_very_verbose("Target %s does not support %s.",
|
||||
_cache_module, _features[i].feature);
|
||||
}
|
||||
@@ -300,7 +294,7 @@ static int _modules_needed(struct dm_pool *mem,
|
||||
const struct lv_segment *seg __attribute__((unused)),
|
||||
struct dm_list *modules)
|
||||
{
|
||||
if (!str_list_add(mem, modules, MODULE_NAME_CACHE)) {
|
||||
if (!str_list_add(mem, modules, "cache")) {
|
||||
log_error("String list allocation failed for cache module.");
|
||||
return 0;
|
||||
}
|
||||
@@ -354,12 +348,12 @@ static int _cache_text_import(struct lv_segment *seg,
|
||||
|
||||
seg->lv->status |= strstr(seg->lv->name, "_corig") ? LV_PENDING_DELETE : 0;
|
||||
|
||||
if (!attach_pool_lv(seg, pool_lv, NULL, NULL, NULL))
|
||||
if (!attach_pool_lv(seg, pool_lv, NULL, NULL))
|
||||
return_0;
|
||||
|
||||
/* load order is unknown, could be cache origin or pool LV, so check for both */
|
||||
if (!dm_list_empty(&pool_lv->segments))
|
||||
_fix_missing_defaults(first_seg(pool_lv));
|
||||
if (!dm_list_empty(&pool_lv->segments) &&
|
||||
!_fix_missing_defaults(first_seg(pool_lv)))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -398,7 +392,6 @@ static int _cache_add_target_line(struct dev_manager *dm,
|
||||
{
|
||||
struct lv_segment *cache_pool_seg;
|
||||
char *metadata_uuid, *data_uuid, *origin_uuid;
|
||||
uint64_t feature_flags = 0;
|
||||
|
||||
if (!seg->pool_lv || !seg_is_cache(seg)) {
|
||||
log_error(INTERNAL_ERROR "Passed segment is not cache.");
|
||||
@@ -406,25 +399,6 @@ static int _cache_add_target_line(struct dev_manager *dm,
|
||||
}
|
||||
|
||||
cache_pool_seg = first_seg(seg->pool_lv);
|
||||
if (seg->cleaner_policy)
|
||||
/* With cleaner policy always pass writethrough */
|
||||
feature_flags |= DM_CACHE_FEATURE_WRITETHROUGH;
|
||||
else
|
||||
switch (cache_pool_seg->cache_mode) {
|
||||
default:
|
||||
log_error(INTERNAL_ERROR "LV %s has unknown cache mode %d.",
|
||||
display_lvname(seg->lv), cache_pool_seg->cache_mode);
|
||||
/* Fall through */
|
||||
case CACHE_MODE_WRITETHROUGH:
|
||||
feature_flags |= DM_CACHE_FEATURE_WRITETHROUGH;
|
||||
break;
|
||||
case CACHE_MODE_WRITEBACK:
|
||||
feature_flags |= DM_CACHE_FEATURE_WRITEBACK;
|
||||
break;
|
||||
case CACHE_MODE_PASSTHROUGH:
|
||||
feature_flags |= DM_CACHE_FEATURE_PASSTHROUGH;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(metadata_uuid = build_dm_uuid(mem, cache_pool_seg->metadata_lv, NULL)))
|
||||
return_0;
|
||||
@@ -436,7 +410,7 @@ static int _cache_add_target_line(struct dev_manager *dm,
|
||||
return_0;
|
||||
|
||||
if (!dm_tree_node_add_cache_target(node, len,
|
||||
feature_flags,
|
||||
cache_pool_seg->feature_flags,
|
||||
metadata_uuid,
|
||||
data_uuid,
|
||||
origin_uuid,
|
||||
|
@@ -278,8 +278,6 @@ static int _parse_debug_classes(struct cmd_context *cmd)
|
||||
debug_classes |= LOG_CLASS_LOCKING;
|
||||
else if (!strcasecmp(cv->v.str, "lvmpolld"))
|
||||
debug_classes |= LOG_CLASS_LVMPOLLD;
|
||||
else if (!strcasecmp(cv->v.str, "dbus"))
|
||||
debug_classes |= LOG_CLASS_DBUS;
|
||||
else
|
||||
log_verbose("Unrecognised value for log/debug_classes: %s", cv->v.str);
|
||||
}
|
||||
@@ -365,7 +363,7 @@ static void _init_logging(struct cmd_context *cmd)
|
||||
/* Tell device-mapper about our logging */
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
if (!dm_log_is_non_default())
|
||||
dm_log_with_errno_init(print_log_libdm);
|
||||
dm_log_with_errno_init(print_log);
|
||||
#endif
|
||||
reset_log_duplicated();
|
||||
reset_lvm_errno(1);
|
||||
@@ -677,9 +675,6 @@ static int _process_config(struct cmd_context *cmd)
|
||||
if (!process_profilable_config(cmd))
|
||||
return_0;
|
||||
|
||||
if (find_config_tree_bool(cmd, report_two_word_unknown_device_CFG, NULL))
|
||||
init_unknown_device_name("unknown device");
|
||||
|
||||
init_detect_internal_vg_cache_corruption
|
||||
(find_config_tree_bool(cmd, global_detect_internal_vg_cache_corruption_CFG, NULL));
|
||||
|
||||
@@ -950,9 +945,6 @@ static void _destroy_config(struct cmd_context *cmd)
|
||||
* they will get loaded again automatically.
|
||||
*/
|
||||
dm_list_iterate_items_safe(profile, tmp_profile, &cmd->profile_params->profiles) {
|
||||
if (cmd->is_interactive && (profile == cmd->profile_params->shell_profile))
|
||||
continue;
|
||||
|
||||
config_destroy(profile->cft);
|
||||
profile->cft = NULL;
|
||||
dm_list_move(&cmd->profile_params->profiles_to_load, &profile->list);
|
||||
@@ -1056,7 +1048,7 @@ static int _init_dev_cache(struct cmd_context *cmd)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define MAX_FILTERS 9
|
||||
#define MAX_FILTERS 8
|
||||
|
||||
static struct dev_filter *_init_lvmetad_filter_chain(struct cmd_context *cmd)
|
||||
{
|
||||
@@ -1081,13 +1073,6 @@ static struct dev_filter *_init_lvmetad_filter_chain(struct cmd_context *cmd)
|
||||
nr_filt++;
|
||||
}
|
||||
|
||||
/* internal filter used by command processing. */
|
||||
if (!(filters[nr_filt] = internal_filter_create())) {
|
||||
log_error("Failed to create internal device filter");
|
||||
goto bad;
|
||||
}
|
||||
nr_filt++;
|
||||
|
||||
/* global regex filter. Optional. */
|
||||
if ((cn = find_config_tree_node(cmd, devices_global_filter_CFG, NULL))) {
|
||||
if (!(filters[nr_filt] = regex_filter_create(cn->v))) {
|
||||
@@ -1169,7 +1154,7 @@ bad:
|
||||
* If lvmetad is used, there are three filter chains:
|
||||
*
|
||||
* - cmd->lvmetad_filter - the lvmetad filter chain used when scanning devs for lvmetad update:
|
||||
* sysfs filter -> internal filter -> global regex filter -> type filter ->
|
||||
* sysfs filter -> global regex filter -> type filter ->
|
||||
* usable device filter(FILTER_MODE_PRE_LVMETAD) ->
|
||||
* mpath component filter -> partitioned filter ->
|
||||
* md component filter -> fw raid filter
|
||||
@@ -1183,7 +1168,7 @@ bad:
|
||||
* If lvmetad is not used, there's just one filter chain:
|
||||
*
|
||||
* - cmd->filter == cmd->full_filter:
|
||||
* persistent filter -> sysfs filter -> internal filter -> global regex filter ->
|
||||
* persistent filter -> sysfs filter -> global regex filter ->
|
||||
* regex_filter -> type filter -> usable device filter(FILTER_MODE_NO_LVMETAD) ->
|
||||
* mpath component filter -> partitioned filter -> md component filter -> fw raid filter
|
||||
*
|
||||
@@ -1653,24 +1638,35 @@ static void _init_globals(struct cmd_context *cmd)
|
||||
}
|
||||
|
||||
/*
|
||||
* init_connections();
|
||||
* _init_lvmetad();
|
||||
* lvmetad_disconnect(); (close previous connection)
|
||||
* lvmetad_set_socket(); (set path from config)
|
||||
* lvmetad_set_token(); (set token from filter config)
|
||||
* if (find_config(use_lvmetad))
|
||||
* lvmetad_connect();
|
||||
*
|
||||
* If lvmetad_connect() is successful, lvmetad_used() will
|
||||
* return 1.
|
||||
*
|
||||
* If the config has use_lvmetad=0, then lvmetad_connect()
|
||||
* will not be called, and lvmetad_used() will return 0.
|
||||
*
|
||||
* Other code should use lvmetad_used() to check if the
|
||||
* command is using lvmetad.
|
||||
*
|
||||
* Close and reopen stream on file descriptor fd.
|
||||
*/
|
||||
static int _reopen_stream(FILE *stream, int fd, const char *mode, const char *name, FILE **new_stream)
|
||||
{
|
||||
int fd_copy, new_fd;
|
||||
|
||||
if ((fd_copy = dup(fd)) < 0) {
|
||||
log_sys_error("dup", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fclose(stream))
|
||||
log_sys_error("fclose", name);
|
||||
|
||||
if ((new_fd = dup2(fd_copy, fd)) < 0)
|
||||
log_sys_error("dup2", name);
|
||||
else if (new_fd != fd)
|
||||
log_error("dup2(%d, %d) returned %d", fd_copy, fd, new_fd);
|
||||
|
||||
if (close(fd_copy) < 0)
|
||||
log_sys_error("close", name);
|
||||
|
||||
if (!(*new_stream = fdopen(fd, mode))) {
|
||||
log_sys_error("fdopen", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _init_lvmetad(struct cmd_context *cmd)
|
||||
{
|
||||
@@ -1694,29 +1690,13 @@ static int _init_lvmetad(struct cmd_context *cmd)
|
||||
|
||||
if (find_config_tree_int(cmd, global_locking_type_CFG, NULL) == 3 &&
|
||||
find_config_tree_bool(cmd, global_use_lvmetad_CFG, NULL)) {
|
||||
log_warn("WARNING: Not using lvmetad because locking_type is 3 (clustered).");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!find_config_tree_bool(cmd, global_use_lvmetad_CFG, NULL)) {
|
||||
if (lvmetad_pidfile_present()) {
|
||||
log_warn("WARNING: Not using lvmetad because config setting use_lvmetad=0.");
|
||||
log_warn("WARNING: To avoid corruption, rescan devices to make changes visible (pvscan --cache).");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!lvmetad_connect(cmd)) {
|
||||
log_warn("WARNING: Failed to connect to lvmetad. Falling back to device scanning.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!lvmetad_used()) {
|
||||
/* This should never happen. */
|
||||
log_error(INTERNAL_ERROR "lvmetad setup incorrect");
|
||||
return 0;
|
||||
}
|
||||
log_warn("WARNING: configuration setting use_lvmetad overridden to 0 due to locking_type 3. "
|
||||
"Clustered environment not supported by lvmetad yet.");
|
||||
lvmetad_set_active(NULL, 0);
|
||||
} else
|
||||
lvmetad_set_active(NULL, find_config_tree_bool(cmd, global_use_lvmetad_CFG, NULL));
|
||||
|
||||
lvmetad_init(cmd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1755,66 +1735,6 @@ bad:
|
||||
return 0;
|
||||
}
|
||||
|
||||
void destroy_config_context(struct cmd_context *cmd)
|
||||
{
|
||||
_destroy_config(cmd);
|
||||
|
||||
if (cmd->mem)
|
||||
dm_pool_destroy(cmd->mem);
|
||||
if (cmd->libmem)
|
||||
dm_pool_destroy(cmd->libmem);
|
||||
|
||||
dm_free(cmd);
|
||||
}
|
||||
|
||||
/*
|
||||
* A "config context" is a very light weight toolcontext that
|
||||
* is only used for reading config settings from lvm.conf.
|
||||
*/
|
||||
struct cmd_context *create_config_context(void)
|
||||
{
|
||||
struct cmd_context *cmd;
|
||||
|
||||
if (!(cmd = dm_zalloc(sizeof(*cmd))))
|
||||
goto_out;
|
||||
|
||||
strcpy(cmd->system_dir, DEFAULT_SYS_DIR);
|
||||
|
||||
if (!_get_env_vars(cmd))
|
||||
goto_out;
|
||||
|
||||
if (!(cmd->libmem = dm_pool_create("library", 4 * 1024)))
|
||||
goto_out;
|
||||
|
||||
dm_list_init(&cmd->config_files);
|
||||
dm_list_init(&cmd->tags);
|
||||
|
||||
if (!_init_lvm_conf(cmd))
|
||||
goto_out;
|
||||
|
||||
if (!_init_hostname(cmd))
|
||||
goto_out;
|
||||
|
||||
if (!_init_tags(cmd, cmd->cft))
|
||||
goto_out;
|
||||
|
||||
/* Load lvmlocal.conf */
|
||||
if (*cmd->system_dir && !_load_config_file(cmd, "", 1))
|
||||
goto_out;
|
||||
|
||||
if (!_init_tag_configs(cmd))
|
||||
goto_out;
|
||||
|
||||
if (!(cmd->cft = _merge_config_files(cmd, cmd->cft)))
|
||||
goto_out;
|
||||
|
||||
return cmd;
|
||||
out:
|
||||
if (cmd)
|
||||
destroy_config_context(cmd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Entry point */
|
||||
struct cmd_context *create_toolcontext(unsigned is_long_lived,
|
||||
const char *system_dir,
|
||||
@@ -1824,6 +1744,7 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived,
|
||||
unsigned set_filters)
|
||||
{
|
||||
struct cmd_context *cmd;
|
||||
FILE *new_stream;
|
||||
int flags;
|
||||
|
||||
#ifdef M_MMAP_MAX
|
||||
@@ -1873,8 +1794,9 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived,
|
||||
if (is_valid_fd(STDIN_FILENO) &&
|
||||
((flags = fcntl(STDIN_FILENO, F_GETFL)) > 0) &&
|
||||
(flags & O_ACCMODE) != O_WRONLY) {
|
||||
if (!reopen_standard_stream(&stdin, "r"))
|
||||
if (!_reopen_stream(stdin, STDIN_FILENO, "r", "stdin", &new_stream))
|
||||
goto_out;
|
||||
stdin = new_stream;
|
||||
if (setvbuf(stdin, cmd->linebuffer, _IOLBF, linebuffer_size)) {
|
||||
log_sys_error("setvbuf", "");
|
||||
goto out;
|
||||
@@ -1884,8 +1806,9 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived,
|
||||
if (is_valid_fd(STDOUT_FILENO) &&
|
||||
((flags = fcntl(STDOUT_FILENO, F_GETFL)) > 0) &&
|
||||
(flags & O_ACCMODE) != O_RDONLY) {
|
||||
if (!reopen_standard_stream(&stdout, "w"))
|
||||
if (!_reopen_stream(stdout, STDOUT_FILENO, "w", "stdout", &new_stream))
|
||||
goto_out;
|
||||
stdout = new_stream;
|
||||
if (setvbuf(stdout, cmd->linebuffer + linebuffer_size,
|
||||
_IOLBF, linebuffer_size)) {
|
||||
log_sys_error("setvbuf", "");
|
||||
@@ -1897,6 +1820,7 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived,
|
||||
/* Without buffering, must not use stdin/stdout */
|
||||
init_silent(1);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Environment variable LVM_SYSTEM_DIR overrides this below.
|
||||
*/
|
||||
@@ -1969,8 +1893,6 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived,
|
||||
if (!init_lvmcache_orphans(cmd))
|
||||
goto_out;
|
||||
|
||||
dm_list_init(&cmd->unused_duplicate_devs);
|
||||
|
||||
if (!_init_segtypes(cmd))
|
||||
goto_out;
|
||||
|
||||
@@ -1982,7 +1904,7 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived,
|
||||
_init_globals(cmd);
|
||||
|
||||
if (set_connections && !init_connections(cmd))
|
||||
goto_out;
|
||||
return_0;
|
||||
|
||||
if (set_filters && !init_filters(cmd, 1))
|
||||
goto_out;
|
||||
@@ -2212,6 +2134,7 @@ int refresh_toolcontext(struct cmd_context *cmd)
|
||||
void destroy_toolcontext(struct cmd_context *cmd)
|
||||
{
|
||||
struct dm_config_tree *cft_cmdline;
|
||||
FILE *new_stream;
|
||||
int flags;
|
||||
|
||||
if (cmd->dump_filter && cmd->filter && cmd->filter->dump &&
|
||||
@@ -2247,18 +2170,20 @@ void destroy_toolcontext(struct cmd_context *cmd)
|
||||
if (is_valid_fd(STDIN_FILENO) &&
|
||||
((flags = fcntl(STDIN_FILENO, F_GETFL)) > 0) &&
|
||||
(flags & O_ACCMODE) != O_WRONLY) {
|
||||
if (reopen_standard_stream(&stdin, "r"))
|
||||
if (_reopen_stream(stdin, STDIN_FILENO, "r", "stdin", &new_stream)) {
|
||||
stdin = new_stream;
|
||||
setlinebuf(stdin);
|
||||
else
|
||||
} else
|
||||
cmd->linebuffer = NULL; /* Leave buffer in place (deliberate leak) */
|
||||
}
|
||||
|
||||
if (is_valid_fd(STDOUT_FILENO) &&
|
||||
((flags = fcntl(STDOUT_FILENO, F_GETFL)) > 0) &&
|
||||
(flags & O_ACCMODE) != O_RDONLY) {
|
||||
if (reopen_standard_stream(&stdout, "w"))
|
||||
if (_reopen_stream(stdout, STDOUT_FILENO, "w", "stdout", &new_stream)) {
|
||||
stdout = new_stream;
|
||||
setlinebuf(stdout);
|
||||
else
|
||||
} else
|
||||
cmd->linebuffer = NULL; /* Leave buffer in place (deliberate leak) */
|
||||
}
|
||||
|
||||
|
@@ -66,15 +66,6 @@ struct cmd_context_initialized_parts {
|
||||
unsigned connections:1;
|
||||
};
|
||||
|
||||
struct cmd_report {
|
||||
int log_only;
|
||||
dm_report_group_type_t report_group_type;
|
||||
struct dm_report_group *report_group;
|
||||
struct dm_report *log_rh;
|
||||
const char *log_name;
|
||||
log_report_t saved_log_report_state;
|
||||
};
|
||||
|
||||
/* FIXME Split into tool & library contexts */
|
||||
/* command-instance-related variables needed by library */
|
||||
struct cmd_context {
|
||||
@@ -88,19 +79,11 @@ 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 *opt_arg_values;
|
||||
struct arg_values *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.
|
||||
*/
|
||||
@@ -130,7 +113,6 @@ struct cmd_context {
|
||||
* Switches.
|
||||
*/
|
||||
unsigned is_long_lived:1; /* optimises persistent_filter handling */
|
||||
unsigned is_interactive:1;
|
||||
unsigned check_pv_dev_sizes:1;
|
||||
unsigned handles_missing_pvs:1;
|
||||
unsigned handles_unknown_segments:1;
|
||||
@@ -146,8 +128,6 @@ struct cmd_context {
|
||||
unsigned threaded:1; /* set if running within a thread e.g. clvmd */
|
||||
unsigned independent_metadata_areas:1; /* active formats have MDAs outside PVs */
|
||||
unsigned unknown_system_id:1;
|
||||
unsigned include_historical_lvs:1; /* also process/report/display historical LVs */
|
||||
unsigned record_historical_lvs:1; /* record historical LVs */
|
||||
unsigned include_foreign_vgs:1; /* report/display cmds can reveal foreign VGs */
|
||||
unsigned include_shared_vgs:1; /* report/display cmds can reveal lockd VGs */
|
||||
unsigned include_active_foreign_vgs:1; /* cmd should process foreign VGs with active LVs */
|
||||
@@ -159,9 +139,6 @@ struct cmd_context {
|
||||
unsigned lockd_vg_rescan:1;
|
||||
unsigned lockd_vg_default_sh:1;
|
||||
unsigned lockd_vg_enforce_sh:1;
|
||||
unsigned vg_notify:1;
|
||||
unsigned lv_notify:1;
|
||||
unsigned pv_notify:1;
|
||||
|
||||
/*
|
||||
* Filtering.
|
||||
@@ -202,11 +179,6 @@ struct cmd_context {
|
||||
char dev_dir[PATH_MAX];
|
||||
char proc_dir[PATH_MAX];
|
||||
|
||||
/*
|
||||
* Reporting.
|
||||
*/
|
||||
struct cmd_report cmd_report;
|
||||
|
||||
/*
|
||||
* Buffers.
|
||||
*/
|
||||
@@ -220,7 +192,6 @@ struct cmd_context {
|
||||
const char *report_list_item_separator;
|
||||
const char *time_format;
|
||||
unsigned rand_seed;
|
||||
struct dm_list unused_duplicate_devs; /* save preferences between lvmcache instances */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -242,14 +213,6 @@ int init_lvmcache_orphans(struct cmd_context *cmd);
|
||||
int init_filters(struct cmd_context *cmd, unsigned load_persistent_cache);
|
||||
int init_connections(struct cmd_context *cmd);
|
||||
|
||||
/*
|
||||
* A config context is a very light weight cmd struct that
|
||||
* is only used for reading config settings from lvm.conf,
|
||||
* which are at cmd->cft.
|
||||
*/
|
||||
struct cmd_context *create_config_context(void);
|
||||
void destroy_config_context(struct cmd_context *cmd);
|
||||
|
||||
struct format_type *get_format_by_name(struct cmd_context *cmd, const char *format);
|
||||
|
||||
const char *system_id_from_string(struct cmd_context *cmd, const char *str);
|
||||
|
@@ -385,13 +385,6 @@ int override_config_tree_from_string(struct cmd_context *cmd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cmd->is_interactive &&
|
||||
!config_force_check(cmd, CONFIG_STRING, cft_new)) {
|
||||
log_error("Ignoring invalid configuration string.");
|
||||
dm_config_destroy(cft_new);
|
||||
return_0;
|
||||
}
|
||||
|
||||
if (!(cs = dm_pool_zalloc(cft_new->mem, sizeof(struct config_source)))) {
|
||||
log_error("Failed to allocate config source.");
|
||||
dm_config_destroy(cft_new);
|
||||
@@ -496,7 +489,7 @@ int override_config_tree_from_profile(struct cmd_context *cmd,
|
||||
int config_file_read_fd(struct dm_config_tree *cft, struct device *dev,
|
||||
off_t offset, size_t size, off_t offset2, size_t size2,
|
||||
checksum_fn_t checksum_fn, uint32_t checksum,
|
||||
int checksum_only, int no_dup_node_check)
|
||||
int checksum_only)
|
||||
{
|
||||
char *fb, *fe;
|
||||
int r = 0;
|
||||
@@ -547,13 +540,8 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev,
|
||||
|
||||
if (!checksum_only) {
|
||||
fe = fb + size + size2;
|
||||
if (no_dup_node_check) {
|
||||
if (!dm_config_parse_without_dup_node_check(cft, fb, fe))
|
||||
goto_out;
|
||||
} else {
|
||||
if (!dm_config_parse(cft, fb, fe))
|
||||
goto_out;
|
||||
}
|
||||
if (!dm_config_parse(cft, fb, fe))
|
||||
goto_out;
|
||||
}
|
||||
|
||||
r = 1;
|
||||
@@ -601,7 +589,7 @@ int config_file_read(struct dm_config_tree *cft)
|
||||
}
|
||||
|
||||
r = config_file_read_fd(cft, cf->dev, 0, (size_t) info.st_size, 0, 0,
|
||||
(checksum_fn_t) NULL, 0, 0, 0);
|
||||
(checksum_fn_t) NULL, 0, 0);
|
||||
|
||||
if (!cf->keep_open) {
|
||||
if (!dev_close(cf->dev))
|
||||
@@ -996,20 +984,6 @@ static int _config_def_check_node_is_profilable(struct cft_check_handle *handle,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _config_def_check_node_is_allowed(struct cft_check_handle *handle,
|
||||
const char *rp, struct dm_config_node *cn,
|
||||
const cfg_def_item_t *def)
|
||||
{
|
||||
if (handle->disallowed_flags & def->flags) {
|
||||
log_warn_suppress(handle->suppress_messages,
|
||||
"Configuration %s \"%s\" is not allowed here.",
|
||||
cn->v ? "option" : "section", rp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _config_def_check_node(struct cft_check_handle *handle,
|
||||
const char *vp, char *pvp, char *rp, char *prp,
|
||||
size_t buf_size, struct dm_config_node *cn)
|
||||
@@ -1060,9 +1034,6 @@ static int _config_def_check_node(struct cft_check_handle *handle,
|
||||
!_config_def_check_node_is_profilable(handle, rp, cn, def))
|
||||
return_0;
|
||||
|
||||
if (!_config_def_check_node_is_allowed(handle, rp, cn, def))
|
||||
return_0;
|
||||
|
||||
handle->status[def->id] |= CFG_VALID;
|
||||
return 1;
|
||||
}
|
||||
@@ -2142,7 +2113,7 @@ bad:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int config_force_check(struct cmd_context *cmd, config_source_t source, struct dm_config_tree *cft)
|
||||
static int _check_profile(struct cmd_context *cmd, struct profile *profile)
|
||||
{
|
||||
struct cft_check_handle *handle;
|
||||
int r;
|
||||
@@ -2153,19 +2124,13 @@ int config_force_check(struct cmd_context *cmd, config_source_t source, struct d
|
||||
}
|
||||
|
||||
handle->cmd = cmd;
|
||||
handle->cft = cft;
|
||||
handle->source = source;
|
||||
handle->cft = profile->cft;
|
||||
handle->source = profile->source;
|
||||
/* the check is compulsory - allow only profilable items in a profile config! */
|
||||
handle->force_check = 1;
|
||||
/* provide warning messages only if config/checks=1 */
|
||||
handle->suppress_messages = !find_config_tree_bool(cmd, config_checks_CFG, NULL);
|
||||
|
||||
/*
|
||||
* Some settings can't be changed if we're running commands interactively
|
||||
* within lvm shell so check for them in case we're in this interactive mode.
|
||||
*/
|
||||
if (cmd->is_interactive)
|
||||
handle->disallowed_flags |= CFG_DISALLOW_INTERACTIVE;
|
||||
|
||||
r = config_def_check(handle);
|
||||
|
||||
dm_pool_free(cmd->libmem, handle);
|
||||
@@ -2287,7 +2252,7 @@ int load_profile(struct cmd_context *cmd, struct profile *profile) {
|
||||
* messages to be suppressed, but the check itself is always done
|
||||
* for profiles!
|
||||
*/
|
||||
if (!config_force_check(cmd, profile->source, profile->cft)) {
|
||||
if (!_check_profile(cmd, profile)) {
|
||||
log_error("Ignoring invalid %s %s.",
|
||||
_config_source_names[profile->source], profile->name);
|
||||
config_destroy(profile->cft);
|
||||
@@ -2466,25 +2431,3 @@ int get_default_allocation_cache_pool_chunk_size_CFG(struct cmd_context *cmd, st
|
||||
{
|
||||
return DEFAULT_CACHE_POOL_CHUNK_SIZE * 2;
|
||||
}
|
||||
|
||||
uint64_t get_default_allocation_cache_pool_max_chunks_CFG(struct cmd_context *cmd, struct profile *profile)
|
||||
{
|
||||
static int _warn_max_chunks = 0;
|
||||
/*
|
||||
* TODO: In future may depend on the cache target version,
|
||||
* newer targets may scale better.
|
||||
*/
|
||||
uint64_t default_max_chunks = DEFAULT_CACHE_POOL_MAX_CHUNKS;
|
||||
uint64_t max_chunks = find_config_tree_int(cmd, allocation_cache_pool_max_chunks_CFG, profile);
|
||||
|
||||
if (!max_chunks)
|
||||
max_chunks = default_max_chunks;
|
||||
else if (max_chunks > default_max_chunks)
|
||||
/* Still warn the user when the value is tweaked above recommended level */
|
||||
/* Maybe drop to log_verbose... */
|
||||
log_warn_suppress(_warn_max_chunks++, "WARNING: Configured cache_pool_max_chunks value "
|
||||
FMTu64 " is higher then recommended " FMTu64 ".",
|
||||
max_chunks, default_max_chunks);
|
||||
|
||||
return max_chunks;
|
||||
}
|
||||
|
@@ -48,7 +48,6 @@ struct profile_params {
|
||||
struct profile *global_metadata_profile; /* profile (as given by --metadataprofile cmd arg) that overrides any other VG/LV-based profile */
|
||||
struct dm_list profiles_to_load; /* list of profiles which are only added, but still need to be loaded for any use */
|
||||
struct dm_list profiles; /* list of profiles which are loaded already and which are ready for use */
|
||||
struct profile *shell_profile; /* master profile used in interactive/shell mode */
|
||||
};
|
||||
|
||||
#define CFG_PATH_MAX_LEN 128
|
||||
@@ -99,34 +98,31 @@ typedef union {
|
||||
|
||||
|
||||
/* whether the configuration item name is variable */
|
||||
#define CFG_NAME_VARIABLE 0x0001
|
||||
#define CFG_NAME_VARIABLE 0x001
|
||||
/* whether empty value is allowed */
|
||||
#define CFG_ALLOW_EMPTY 0x0002
|
||||
#define CFG_ALLOW_EMPTY 0x002
|
||||
/* whether the configuration item is for advanced use only */
|
||||
#define CFG_ADVANCED 0x0004
|
||||
#define CFG_ADVANCED 0x004
|
||||
/* whether the configuration item is not officially supported */
|
||||
#define CFG_UNSUPPORTED 0x0008
|
||||
#define CFG_UNSUPPORTED 0x008
|
||||
/* whether the configuration item is customizable by a profile */
|
||||
#define CFG_PROFILABLE 0x0010
|
||||
/* whether the configuration item is customizable by a profile
|
||||
* and whether it can be attached to VG/LV metadata at the same time
|
||||
#define CFG_PROFILABLE 0x010
|
||||
/* whether the configuration item is customizable by a profile */
|
||||
/* and whether it can be attached to VG/LV metadata at the same time
|
||||
* The CFG_PROFILABLE_METADATA flag incorporates CFG_PROFILABLE flag!!! */
|
||||
#define CFG_PROFILABLE_METADATA 0x0030
|
||||
#define CFG_PROFILABLE_METADATA 0x030
|
||||
/* whether the default value is undefned */
|
||||
#define CFG_DEFAULT_UNDEFINED 0x0040
|
||||
#define CFG_DEFAULT_UNDEFINED 0x040
|
||||
/* whether the default value is commented out on output */
|
||||
#define CFG_DEFAULT_COMMENTED 0x0080
|
||||
#define CFG_DEFAULT_COMMENTED 0x080
|
||||
/* whether the default value is calculated during run time */
|
||||
#define CFG_DEFAULT_RUN_TIME 0x0100
|
||||
#define CFG_DEFAULT_RUN_TIME 0x100
|
||||
/* whether the configuration setting is disabled (and hence defaults always used) */
|
||||
#define CFG_DISABLED 0x0200
|
||||
#define CFG_DISABLED 0x200
|
||||
/* whether to print integers in octal form (prefixed by "0") */
|
||||
#define CFG_FORMAT_INT_OCTAL 0x0400
|
||||
#define CFG_FORMAT_INT_OCTAL 0x400
|
||||
/* whether to disable checks for the whole config section subtree */
|
||||
#define CFG_SECTION_NO_CHECK 0x0800
|
||||
/* whether to disallow a possibility to override configuration
|
||||
* setting for commands run interactively (e.g. in lvm shell) */
|
||||
#define CFG_DISALLOW_INTERACTIVE 0x1000
|
||||
#define CFG_SECTION_NO_CHECK 0x800
|
||||
|
||||
/* configuration definition item structure */
|
||||
typedef struct cfg_def_item {
|
||||
@@ -216,15 +212,11 @@ struct cft_check_handle {
|
||||
unsigned check_diff:1; /* check if the value used differs from default one */
|
||||
unsigned ignoreadvanced:1; /* do not include advnced configs */
|
||||
unsigned ignoreunsupported:1; /* do not include unsupported configs */
|
||||
uint16_t disallowed_flags; /* set of disallowed flags */
|
||||
uint8_t status[CFG_COUNT]; /* flags for each configuration item - the result of the check */
|
||||
};
|
||||
|
||||
int config_def_get_path(char *buf, size_t buf_size, int id);
|
||||
/* Checks config using given handle - the handle may be reused. */
|
||||
int config_def_check(struct cft_check_handle *handle);
|
||||
/* Forces config check and automatically creates a new handle inside with defaults and discards the handle after the check. */
|
||||
int config_force_check(struct cmd_context *cmd, config_source_t source, struct dm_config_tree *cft);
|
||||
|
||||
int override_config_tree_from_string(struct cmd_context *cmd, const char *config_settings);
|
||||
int override_config_tree_from_profile(struct cmd_context *cmd, struct profile *profile);
|
||||
@@ -239,7 +231,7 @@ struct dm_config_tree *config_open(config_source_t source, const char *filename,
|
||||
int config_file_read_fd(struct dm_config_tree *cft, struct device *dev,
|
||||
off_t offset, size_t size, off_t offset2, size_t size2,
|
||||
checksum_fn_t checksum_fn, uint32_t checksum,
|
||||
int skip_parse, int no_dup_node_check);
|
||||
int skip_parse);
|
||||
int config_file_read(struct dm_config_tree *cft);
|
||||
struct dm_config_tree *config_file_open_and_read(const char *config_file, config_source_t source,
|
||||
struct cmd_context *cmd);
|
||||
@@ -307,6 +299,5 @@ int get_default_allocation_cache_pool_chunk_size_CFG(struct cmd_context *cmd, st
|
||||
#define get_default_unconfigured_allocation_cache_pool_chunk_size_CFG NULL
|
||||
const char *get_default_allocation_cache_policy_CFG(struct cmd_context *cmd, struct profile *profile);
|
||||
#define get_default_unconfigured_allocation_cache_policy_CFG NULL
|
||||
uint64_t get_default_allocation_cache_pool_max_chunks_CFG(struct cmd_context *cmd, struct profile *profile);
|
||||
|
||||
#endif
|
||||
|
@@ -23,11 +23,6 @@
|
||||
* - define a configuration array of one or more types:
|
||||
* cfg_array(id, name, parent, flags, types, default_value, since_version, unconfigured_default_value, deprecated_since_version, deprecation_comment, comment)
|
||||
*
|
||||
* - define a configuration setting where the default value is evaluated in runtime
|
||||
* cfg_runtime(id, name, parent, flags, type, since_version, deprecated_since_version, deprecation_comment, comment)
|
||||
* (for each cfg_runtime, you need to define 'get_default_<name>(struct cmd_context *cmd, struct profile *profile)' function
|
||||
* to get the default value in runtime - usually, these functions are placed in config.[ch] file)
|
||||
*
|
||||
*
|
||||
* If default value can't be assigned statically because it depends on some
|
||||
* run-time checks or if it depends on other settings already defined,
|
||||
@@ -57,7 +52,6 @@
|
||||
* CFG_DISABLED - configuration is disabled (defaults always used)
|
||||
* CFG_FORMAT_INT_OCTAL - print integer number in octal form (also prefixed by "0")
|
||||
* CFG_SECTION_NO_CHECK - do not check content of the section at all - use with care!!!
|
||||
* CFG_DISALLOW_INTERACTIVE - disallow configuration node for use in interactive environment (e.g. cmds run in lvm shell)
|
||||
*
|
||||
* type: Allowed type for the value of simple configuation setting, one of:
|
||||
* CFG_TYPE_BOOL
|
||||
@@ -130,7 +124,7 @@ cfg_section(devices_CFG_SECTION, "devices", root_CFG_SECTION, 0, vsn(1, 0, 0), 0
|
||||
cfg_section(allocation_CFG_SECTION, "allocation", root_CFG_SECTION, CFG_PROFILABLE, vsn(2, 2, 77), 0, NULL,
|
||||
"How LVM selects space and applies properties to LVs.\n")
|
||||
|
||||
cfg_section(log_CFG_SECTION, "log", root_CFG_SECTION, CFG_PROFILABLE, vsn(1, 0, 0), 0, NULL,
|
||||
cfg_section(log_CFG_SECTION, "log", root_CFG_SECTION, 0, vsn(1, 0, 0), 0, NULL,
|
||||
"How LVM log information is reported.\n")
|
||||
|
||||
cfg_section(backup_CFG_SECTION, "backup", root_CFG_SECTION, 0, vsn(1, 0, 0), 0, NULL,
|
||||
@@ -172,7 +166,7 @@ cfg(config_checks_CFG, "checks", config_CFG_SECTION, 0, CFG_TYPE_BOOL, 1, vsn(2,
|
||||
cfg(config_abort_on_errors_CFG, "abort_on_errors", config_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2,2,99), NULL, 0, NULL,
|
||||
"Abort the LVM process if a configuration mismatch is found.\n")
|
||||
|
||||
cfg_runtime(config_profile_dir_CFG, "profile_dir", config_CFG_SECTION, CFG_DISALLOW_INTERACTIVE, CFG_TYPE_STRING, vsn(2, 2, 99), 0, NULL,
|
||||
cfg_runtime(config_profile_dir_CFG, "profile_dir", config_CFG_SECTION, 0, CFG_TYPE_STRING, vsn(2, 2, 99), 0, NULL,
|
||||
"Directory where LVM looks for configuration profiles.\n")
|
||||
|
||||
cfg(devices_dir_CFG, "dir", devices_CFG_SECTION, CFG_ADVANCED, CFG_TYPE_STRING, DEFAULT_DEV_DIR, vsn(1, 0, 0), NULL, 0, NULL,
|
||||
@@ -401,18 +395,6 @@ cfg(devices_issue_discards_CFG, "issue_discards", devices_CFG_SECTION, 0, CFG_TY
|
||||
"generally do. If enabled, discards will only be issued if both the\n"
|
||||
"storage and kernel provide support.\n")
|
||||
|
||||
cfg(devices_allow_changes_with_duplicate_pvs_CFG, "allow_changes_with_duplicate_pvs", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_ALLOW_CHANGES_WITH_DUPLICATE_PVS, vsn(2, 2, 153), NULL, 0, NULL,
|
||||
"Allow VG modification while a PV appears on multiple devices.\n"
|
||||
"When a PV appears on multiple devices, LVM attempts to choose the\n"
|
||||
"best device to use for the PV. If the devices represent the same\n"
|
||||
"underlying storage, the choice has minimal consequence. If the\n"
|
||||
"devices represent different underlying storage, the wrong choice\n"
|
||||
"can result in data loss if the VG is modified. Disabling this\n"
|
||||
"setting is the safest option because it prevents modifying a VG\n"
|
||||
"or activating LVs in it while a PV appears on multiple devices.\n"
|
||||
"Enabling this setting allows the VG to be used as usual even with\n"
|
||||
"uncertain devices.\n")
|
||||
|
||||
cfg_array(allocation_cling_tag_list_CFG, "cling_tag_list", allocation_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 2, 77), NULL, 0, NULL,
|
||||
"Advise LVM which PVs to use when searching for new space.\n"
|
||||
"When searching for free space to extend an LV, the 'cling' allocation\n"
|
||||
@@ -467,12 +449,6 @@ cfg(allocation_mirror_logs_require_separate_pvs_CFG, "mirror_logs_require_separa
|
||||
"Mirror logs and images will always use different PVs.\n"
|
||||
"The default setting changed in version 2.02.85.\n")
|
||||
|
||||
cfg(allocation_raid_stripe_all_devices_CFG, "raid_stripe_all_devices", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_ALLOCATION_STRIPE_ALL_DEVICES, vsn(2, 2, 162), NULL, 0, NULL,
|
||||
"Stripe across all PVs when RAID stripes are not specified.\n"
|
||||
"If enabled, all PVs in the VG or on the command line are used for raid0/4/5/6/10\n"
|
||||
"when the command does not specify the number of stripes to use.\n"
|
||||
"This was the default behaviour until release 2.02.162.\n")
|
||||
|
||||
cfg(allocation_cache_pool_metadata_require_separate_pvs_CFG, "cache_pool_metadata_require_separate_pvs", allocation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_CACHE_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 106), NULL, 0, NULL,
|
||||
"Cache pool metadata and data will always use different PVs.\n")
|
||||
|
||||
@@ -516,11 +492,6 @@ cfg_runtime(allocation_cache_pool_chunk_size_CFG, "cache_pool_chunk_size", alloc
|
||||
"on the smaller end of the spectrum. Supported values range from\n"
|
||||
"32KiB to 1GiB in multiples of 32.\n")
|
||||
|
||||
cfg(allocation_cache_pool_max_chunks_CFG, "cache_pool_max_chunks", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_UNDEFINED, CFG_TYPE_INT, 0, vsn(2, 2, 165), NULL, 0, NULL,
|
||||
"The maximum number of chunks in a cache pool.\n"
|
||||
"For cache target v1.9 the recommended maximumm is 1000000 chunks.\n"
|
||||
"Using cache pool with more chunks may degrade cache performance.\n")
|
||||
|
||||
cfg(allocation_thin_pool_metadata_require_separate_pvs_CFG, "thin_pool_metadata_require_separate_pvs", allocation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 89), NULL, 0, NULL,
|
||||
"Thin pool metdata and data will always use different PVs.\n")
|
||||
|
||||
@@ -564,47 +535,6 @@ cfg_runtime(allocation_thin_pool_chunk_size_CFG, "thin_pool_chunk_size", allocat
|
||||
cfg(allocation_physical_extent_size_CFG, "physical_extent_size", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_EXTENT_SIZE, vsn(2, 2, 112), NULL, 0, NULL,
|
||||
"Default physical extent size in KiB to use for new VGs.\n")
|
||||
|
||||
cfg(log_report_command_log_CFG, "report_command_log", log_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED | CFG_DISALLOW_INTERACTIVE, CFG_TYPE_BOOL, DEFAULT_COMMAND_LOG_REPORT, vsn(2, 2, 158), NULL, 0, NULL,
|
||||
"Enable or disable LVM log reporting.\n"
|
||||
"If enabled, LVM will collect a log of operations, messages,\n"
|
||||
"per-object return codes with object identification and associated\n"
|
||||
"error numbers (errnos) during LVM command processing. Then the\n"
|
||||
"log is either reported solely or in addition to any existing\n"
|
||||
"reports, depending on LVM command used. If it is a reporting command\n"
|
||||
"(e.g. pvs, vgs, lvs, lvm fullreport), then the log is reported in\n"
|
||||
"addition to any existing reports. Otherwise, there's only log report\n"
|
||||
"on output. For all applicable LVM commands, you can request that\n"
|
||||
"the output has only log report by using --logonly command line\n"
|
||||
"option. Use log/command_log_cols and log/command_log_sort settings\n"
|
||||
"to define fields to display and sort fields for the log report.\n"
|
||||
"You can also use log/command_log_selection to define selection\n"
|
||||
"criteria used each time the log is reported.\n")
|
||||
|
||||
cfg(log_command_log_sort_CFG, "command_log_sort", log_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED | CFG_DISALLOW_INTERACTIVE, CFG_TYPE_STRING, DEFAULT_COMMAND_LOG_SORT, vsn(2, 2, 158), NULL, 0, NULL,
|
||||
"List of columns to sort by when reporting command log.\n"
|
||||
"See <lvm command> --logonly --configreport log -o help\n"
|
||||
"for the list of possible fields.\n")
|
||||
|
||||
cfg(log_command_log_cols_CFG, "command_log_cols", log_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED | CFG_DISALLOW_INTERACTIVE, CFG_TYPE_STRING, DEFAULT_COMMAND_LOG_COLS, vsn(2, 2, 158), NULL, 0, NULL,
|
||||
"List of columns to report when reporting command log.\n"
|
||||
"See <lvm command> --logonly --configreport log -o help\n"
|
||||
"for the list of possible fields.\n")
|
||||
|
||||
cfg(log_command_log_selection_CFG, "command_log_selection", log_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED | CFG_DISALLOW_INTERACTIVE, CFG_TYPE_STRING, DEFAULT_COMMAND_LOG_SELECTION, vsn(2, 2, 158), NULL, 0, NULL,
|
||||
"Selection criteria used when reporting command log.\n"
|
||||
"You can define selection criteria that are applied each\n"
|
||||
"time log is reported. This way, it is possible to control the\n"
|
||||
"amount of log that is displayed on output and you can select\n"
|
||||
"only parts of the log that are important for you. To define\n"
|
||||
"selection criteria, use fields from log report. See also\n"
|
||||
"<lvm command> --logonly --configreport log -S help for the\n"
|
||||
"list of possible fields and selection operators. You can also\n"
|
||||
"define selection criteria for log report on command line directly\n"
|
||||
"using <lvm command> --configreport log -S <selection criteria>\n"
|
||||
"which has precedence over log/command_log_selection setting.\n"
|
||||
"For more information about selection criteria in general, see\n"
|
||||
"lvm(8) man page.\n")
|
||||
|
||||
cfg(log_verbose_CFG, "verbose", log_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_VERBOSE, vsn(1, 0, 0), NULL, 0, NULL,
|
||||
"Controls the messages sent to stdout or stderr.\n")
|
||||
|
||||
@@ -651,7 +581,7 @@ cfg(log_activation_CFG, "activation", log_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(
|
||||
|
||||
cfg(log_activate_file_CFG, "activate_file", log_CFG_SECTION, CFG_DEFAULT_UNDEFINED | CFG_UNSUPPORTED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, 0, NULL, NULL)
|
||||
|
||||
cfg_array(log_debug_classes_CFG, "debug_classes", log_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, "#Smemory#Sdevices#Sactivation#Sallocation#Slvmetad#Smetadata#Scache#Slocking#Slvmpolld#Sdbus", vsn(2, 2, 99), NULL, 0, NULL,
|
||||
cfg_array(log_debug_classes_CFG, "debug_classes", log_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, "#Smemory#Sdevices#Sactivation#Sallocation#Slvmetad#Smetadata#Scache#Slocking#Slvmpolld", vsn(2, 2, 99), NULL, 0, NULL,
|
||||
"Select log messages by class.\n"
|
||||
"Some debugging messages are assigned to a class and only appear in\n"
|
||||
"debug output if the class is listed here. Classes currently\n"
|
||||
@@ -924,20 +854,12 @@ cfg(global_use_lvmetad_CFG, "use_lvmetad", global_CFG_SECTION, 0, CFG_TYPE_BOOL,
|
||||
"scanning from the LVM system entirely, including lvmetad, use\n"
|
||||
"devices/global_filter.\n")
|
||||
|
||||
cfg(global_lvmetad_update_wait_time_CFG, "lvmetad_update_wait_time", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_LVMETAD_UPDATE_WAIT_TIME, vsn(2, 2, 151), NULL, 0, NULL,
|
||||
"The number of seconds a command will wait for lvmetad update to finish.\n"
|
||||
"After waiting for this period, a command will not use lvmetad, and\n"
|
||||
"will revert to disk scanning.\n")
|
||||
|
||||
cfg(global_use_lvmlockd_CFG, "use_lvmlockd", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 2, 124), NULL, 0, NULL,
|
||||
"Use lvmlockd for locking among hosts using LVM on shared storage.\n"
|
||||
"Applicable only if LVM is compiled with lockd support in which\n"
|
||||
"case there is also lvmlockd(8) man page available for more\n"
|
||||
"information.\n")
|
||||
"See lvmlockd(8) for more information.\n")
|
||||
|
||||
cfg(global_lvmlockd_lock_retries_CFG, "lvmlockd_lock_retries", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_LVMLOCKD_LOCK_RETRIES, vsn(2, 2, 125), NULL, 0, NULL,
|
||||
"Retry lvmlockd lock requests this many times.\n"
|
||||
"Applicable only if LVM is compiled with lockd support\n")
|
||||
"Retry lvmlockd lock requests this many times.\n")
|
||||
|
||||
cfg(global_sanlock_lv_extend_CFG, "sanlock_lv_extend", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_SANLOCK_LV_EXTEND_MB, vsn(2, 2, 124), NULL, 0, NULL,
|
||||
"Size in MiB to extend the internal LV holding sanlock locks.\n"
|
||||
@@ -945,8 +867,7 @@ cfg(global_sanlock_lv_extend_CFG, "sanlock_lv_extend", global_CFG_SECTION, CFG_D
|
||||
"LVs have been created, the internal LV needs to be extended. lvcreate\n"
|
||||
"will automatically extend the internal LV when needed by the amount\n"
|
||||
"specified here. Setting this to 0 disables the automatic extension\n"
|
||||
"and can cause lvcreate to fail. Applicable only if LVM is compiled\n"
|
||||
"with lockd support\n")
|
||||
"and can cause lvcreate to fail.\n")
|
||||
|
||||
cfg(global_thin_check_executable_CFG, "thin_check_executable", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, THIN_CHECK_CMD, vsn(2, 2, 94), "@THIN_CHECK_CMD@", 0, NULL,
|
||||
"The full path to the thin_check command.\n"
|
||||
@@ -1072,13 +993,7 @@ cfg(global_use_lvmpolld_CFG, "use_lvmpolld", global_CFG_SECTION, 0, CFG_TYPE_BOO
|
||||
"manage the progress of ongoing operations. lvmpolld can be used as\n"
|
||||
"a native systemd service, which allows it to be started on demand,\n"
|
||||
"and to use its own control group. When this option is disabled, LVM\n"
|
||||
"commands will supervise long running operations by forking themselves.\n"
|
||||
"Applicable only if LVM is compiled with lvmpolld support.\n")
|
||||
|
||||
cfg(global_notify_dbus_CFG, "notify_dbus", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_NOTIFY_DBUS, vsn(2, 2, 145), NULL, 0, NULL,
|
||||
"Enable D-Bus notification from LVM commands.\n"
|
||||
"When enabled, an LVM command that changes PVs, changes VG metadata,\n"
|
||||
"or changes the activation state of an LV will send a notification.\n")
|
||||
"commands will supervise long running operations by forking themselves.\n")
|
||||
|
||||
cfg(activation_udev_sync_CFG, "udev_sync", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_UDEV_SYNC, vsn(2, 2, 51), NULL, 0, NULL,
|
||||
"Use udev notifications to synchronize udev and LVM.\n"
|
||||
@@ -1445,18 +1360,6 @@ cfg(metadata_check_pv_device_sizes_CFG, "check_pv_device_sizes", metadata_CFG_SE
|
||||
"less than corresponding PV size. You should not disable this unless\n"
|
||||
"you are absolutely sure about what you are doing!\n")
|
||||
|
||||
cfg(metadata_record_lvs_history_CFG, "record_lvs_history", metadata_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_RECORD_LVS_HISTORY, vsn(2, 2, 145), NULL, 0, NULL,
|
||||
"When enabled, LVM keeps history records about removed LVs in\n"
|
||||
"metadata. The information that is recorded in metadata for\n"
|
||||
"historical LVs is reduced when compared to original\n"
|
||||
"information kept in metadata for live LVs. Currently, this\n"
|
||||
"feature is supported for thin and thin snapshot LVs only.\n")
|
||||
|
||||
cfg(metadata_lvs_history_retention_time_CFG, "lvs_history_retention_time", metadata_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_LVS_HISTORY_RETENTION_TIME, vsn(2, 2, 145), NULL, 0, NULL,
|
||||
"Retention time in seconds after which a record about individual\n"
|
||||
"historical logical volume is automatically destroyed.\n"
|
||||
"A value of 0 disables this feature.\n")
|
||||
|
||||
cfg(metadata_pvmetadatacopies_CFG, "pvmetadatacopies", metadata_CFG_SECTION, CFG_ADVANCED | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_PVMETADATACOPIES, vsn(1, 0, 0), NULL, 0, NULL,
|
||||
"Number of copies of metadata to store on each PV.\n"
|
||||
"The --pvmetadatacopies option overrides this setting.\n"
|
||||
@@ -1520,20 +1423,6 @@ cfg(disk_area_start_sector_CFG, "start_sector", disk_area_CFG_SUBSECTION, CFG_UN
|
||||
cfg(disk_area_size_CFG, "size", disk_area_CFG_SUBSECTION, CFG_UNSUPPORTED | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 0, vsn(1, 0, 0), NULL, 0, NULL, NULL)
|
||||
cfg(disk_area_id_CFG, "id", disk_area_CFG_SUBSECTION, CFG_UNSUPPORTED | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, 0, NULL, NULL)
|
||||
|
||||
cfg(report_output_format_CFG, "output_format", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED | CFG_DISALLOW_INTERACTIVE, CFG_TYPE_STRING, DEFAULT_REP_OUTPUT_FORMAT, vsn(2, 2, 158), NULL, 0, NULL,
|
||||
"Format of LVM command's report output.\n"
|
||||
"If there is more than one report per command, then the format\n"
|
||||
"is applied for all reports. You can also change output format\n"
|
||||
"directly on command line using --reportformat option which\n"
|
||||
"has precedence over log/output_format setting.\n"
|
||||
"Accepted values:\n"
|
||||
" basic\n"
|
||||
" Original format with columns and rows. If there is more than\n"
|
||||
" one report per command, each report is prefixed with report's\n"
|
||||
" name for identification.\n"
|
||||
" json\n"
|
||||
" JSON format.\n")
|
||||
|
||||
cfg(report_compact_output_CFG, "compact_output", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_REP_COMPACT_OUTPUT, vsn(2, 2, 115), NULL, 0, NULL,
|
||||
"Do not print empty values for all report fields.\n"
|
||||
"If enabled, all fields that don't have a value set for any of the\n"
|
||||
@@ -1576,7 +1465,7 @@ cfg(report_prefixes_CFG, "prefixes", report_CFG_SECTION, CFG_PROFILABLE | CFG_DE
|
||||
cfg(report_quoted_CFG, "quoted", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_REP_QUOTED, vsn(2, 2, 39), NULL, 0, NULL,
|
||||
"Quote field values when using field name prefixes.\n")
|
||||
|
||||
cfg(report_columns_as_rows_CFG, "columns_as_rows", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_REP_COLUMNS_AS_ROWS, vsn(1, 0, 0), NULL, 0, NULL,
|
||||
cfg(report_colums_as_rows_CFG, "colums_as_rows", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_REP_COLUMNS_AS_ROWS, vsn(1, 0, 0), NULL, 0, NULL,
|
||||
"Output each column as a row.\n"
|
||||
"If set, this also implies report/prefixes=1.\n")
|
||||
|
||||
@@ -1790,53 +1679,9 @@ cfg(report_pvsegs_cols_verbose_CFG, "pvsegs_cols_verbose", report_CFG_SECTION, C
|
||||
"List of columns to sort by when reporting 'pvs --segments' command in verbose mode.\n"
|
||||
"See 'pvs --segments -o help' for the list of possible fields.\n")
|
||||
|
||||
cfg(report_vgs_cols_full_CFG, "vgs_cols_full", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_VGS_COLS_FULL, vsn(2, 2, 158), NULL, 0, NULL,
|
||||
"List of columns to report for lvm fullreport's 'vgs' subreport.\n"
|
||||
"See 'vgs -o help' for the list of possible fields.\n")
|
||||
|
||||
cfg(report_pvs_cols_full_CFG, "pvs_cols_full", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_PVS_COLS_FULL, vsn(2, 2, 158), NULL, 0, NULL,
|
||||
"List of columns to report for lvm fullreport's 'vgs' subreport.\n"
|
||||
"See 'pvs -o help' for the list of possible fields.\n")
|
||||
|
||||
cfg(report_lvs_cols_full_CFG, "lvs_cols_full", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_LVS_COLS_FULL, vsn(2, 2, 158), NULL, 0, NULL,
|
||||
"List of columns to report for lvm fullreport's 'lvs' subreport.\n"
|
||||
"See 'lvs -o help' for the list of possible fields.\n")
|
||||
|
||||
cfg(report_pvsegs_cols_full_CFG, "pvsegs_cols_full", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_PVSEGS_COLS_FULL, vsn(2, 2, 158), NULL, 0, NULL,
|
||||
"List of columns to report for lvm fullreport's 'pvseg' subreport.\n"
|
||||
"See 'pvs --segments -o help' for the list of possible fields.\n")
|
||||
|
||||
cfg(report_segs_cols_full_CFG, "segs_cols_full", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_SEGS_COLS_FULL, vsn(2, 2, 158), NULL, 0, NULL,
|
||||
"List of columns to report for lvm fullreport's 'seg' subreport.\n"
|
||||
"See 'lvs --segments -o help' for the list of possible fields.\n")
|
||||
|
||||
cfg(report_vgs_sort_full_CFG, "vgs_sort_full", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_VGS_SORT_FULL, vsn(2, 2, 158), NULL, 0, NULL,
|
||||
"List of columns to sort by when reporting lvm fullreport's 'vgs' subreport.\n"
|
||||
"See 'vgs -o help' for the list of possible fields.\n")
|
||||
|
||||
cfg(report_pvs_sort_full_CFG, "pvs_sort_full", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_PVS_SORT_FULL, vsn(2, 2, 158), NULL, 0, NULL,
|
||||
"List of columns to sort by when reporting lvm fullreport's 'vgs' subreport.\n"
|
||||
"See 'pvs -o help' for the list of possible fields.\n")
|
||||
|
||||
cfg(report_lvs_sort_full_CFG, "lvs_sort_full", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_LVS_SORT_FULL, vsn(2, 2, 158), NULL, 0, NULL,
|
||||
"List of columns to sort by when reporting lvm fullreport's 'lvs' subreport.\n"
|
||||
"See 'lvs -o help' for the list of possible fields.\n")
|
||||
|
||||
cfg(report_pvsegs_sort_full_CFG, "pvsegs_sort_full", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_PVSEGS_SORT_FULL, vsn(2, 2, 158), NULL, 0, NULL,
|
||||
"List of columns to sort by when reporting for lvm fullreport's 'pvseg' subreport.\n"
|
||||
"See 'pvs --segments -o help' for the list of possible fields.\n")
|
||||
|
||||
cfg(report_segs_sort_full_CFG, "segs_sort_full", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_SEGS_SORT_FULL, vsn(2, 2, 158), NULL, 0, NULL,
|
||||
"List of columns to sort by when reporting lvm fullreport's 'seg' subreport.\n"
|
||||
"See 'lvs --segments -o help' for the list of possible fields.\n")
|
||||
|
||||
cfg(report_mark_hidden_devices_CFG, "mark_hidden_devices", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 1, vsn(2, 2, 140), NULL, 0, NULL,
|
||||
"Use brackets [] to mark hidden devices.\n")
|
||||
|
||||
cfg(report_two_word_unknown_device_CFG, "two_word_unknown_device", report_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(2, 2, 146), NULL, 0, NULL,
|
||||
"Use the two words 'unknown device' in place of '[unknown]'.\n"
|
||||
"This is displayed when the device for a PV is not known.\n")
|
||||
|
||||
cfg(dmeventd_mirror_library_CFG, "mirror_library", dmeventd_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_DMEVENTD_MIRROR_LIB, vsn(1, 2, 3), NULL, 0, NULL,
|
||||
"The library dmeventd uses when monitoring a mirror device.\n"
|
||||
"libdevmapper-event-lvm2mirror.so attempts to recover from\n"
|
||||
@@ -1913,7 +1758,6 @@ cfg_array(local_extra_system_ids_CFG, "extra_system_ids", local_CFG_SECTION, CFG
|
||||
|
||||
cfg(local_host_id_CFG, "host_id", local_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 0, vsn(2, 2, 124), NULL, 0, NULL,
|
||||
"The lvmlockd sanlock host_id.\n"
|
||||
"This must be unique among all hosts, and must be between 1 and 2000.\n"
|
||||
"Applicable only if LVM is compiled with lockd support\n")
|
||||
"This must be unique among all hosts, and must be between 1 and 2000.\n")
|
||||
|
||||
cfg(CFG_COUNT, NULL, root_CFG_SECTION, 0, CFG_TYPE_INT, 0, vsn(0, 0, 0), NULL, 0, NULL, NULL)
|
||||
|
@@ -45,7 +45,6 @@
|
||||
#define DEFAULT_DATA_ALIGNMENT_DETECTION 1
|
||||
#define DEFAULT_ISSUE_DISCARDS 0
|
||||
#define DEFAULT_PV_MIN_SIZE_KB 2048
|
||||
#define DEFAULT_ALLOW_CHANGES_WITH_DUPLICATE_PVS 0
|
||||
|
||||
#define DEFAULT_LOCKING_LIB "liblvm2clusterlock.so"
|
||||
#define DEFAULT_ERROR_WHEN_FULL 0
|
||||
@@ -53,12 +52,10 @@
|
||||
#define DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING 1
|
||||
#define DEFAULT_WAIT_FOR_LOCKS 1
|
||||
#define DEFAULT_LVMLOCKD_LOCK_RETRIES 3
|
||||
#define DEFAULT_LVMETAD_UPDATE_WAIT_TIME 10
|
||||
#define DEFAULT_PRIORITISE_WRITE_LOCKS 1
|
||||
#define DEFAULT_USE_MLOCKALL 0
|
||||
#define DEFAULT_METADATA_READ_ONLY 0
|
||||
#define DEFAULT_LVDISPLAY_SHOWS_FULL_DEVICE_PATH 0
|
||||
#define DEFAULT_UNKNOWN_DEVICE_NAME "[unknown]"
|
||||
|
||||
#define DEFAULT_SANLOCK_LV_EXTEND_MB 256
|
||||
|
||||
@@ -66,14 +63,7 @@
|
||||
#define DEFAULT_MIRROR_LOG_FAULT_POLICY "allocate"
|
||||
#define DEFAULT_MIRROR_IMAGE_FAULT_POLICY "remove"
|
||||
#define DEFAULT_MIRROR_MAX_IMAGES 8 /* limited by kernel DM_KCOPYD_MAX_REGIONS */
|
||||
/* Limited by kernel failed devices bitfield in superblock (raid4/5/6 MD max 253) */
|
||||
/*
|
||||
* FIXME: Increase these to 64 and further to the MD maximum
|
||||
* once the SubLVs split and name shift got enhanced
|
||||
*/
|
||||
#define DEFAULT_RAID1_MAX_IMAGES 10
|
||||
#define DEFAULT_RAID_MAX_IMAGES 64
|
||||
#define DEFAULT_ALLOCATION_STRIPE_ALL_DEVICES 0 /* Don't stripe across all devices if not -i/--stripes given */
|
||||
#define DEFAULT_RAID_MAX_IMAGES 8
|
||||
|
||||
#define DEFAULT_RAID_FAULT_POLICY "warn"
|
||||
|
||||
@@ -127,7 +117,6 @@
|
||||
#define DEFAULT_CACHE_REPAIR_OPTIONS_CONFIG "#S" DEFAULT_CACHE_REPAIR_OPTION1
|
||||
#define DEFAULT_CACHE_POOL_METADATA_REQUIRE_SEPARATE_PVS 0
|
||||
#define DEFAULT_CACHE_POOL_CHUNK_SIZE 64 /* KB */
|
||||
#define DEFAULT_CACHE_POOL_MAX_CHUNKS 1000000
|
||||
#define DEFAULT_CACHE_POOL_MIN_METADATA_SIZE 2048 /* KB */
|
||||
#define DEFAULT_CACHE_POOL_MAX_METADATA_SIZE (16 * 1024 * 1024) /* KB */
|
||||
#define DEFAULT_CACHE_POLICY "mq"
|
||||
@@ -138,8 +127,6 @@
|
||||
#define DEFAULT_FORMAT "lvm2"
|
||||
|
||||
#define DEFAULT_STRIPESIZE 64 /* KB */
|
||||
#define DEFAULT_RECORD_LVS_HISTORY 0
|
||||
#define DEFAULT_LVS_HISTORY_RETENTION_TIME 0
|
||||
#define DEFAULT_PVMETADATAIGNORE 0
|
||||
#define DEFAULT_PVMETADATASIZE 255
|
||||
#define DEFAULT_PVMETADATACOPIES 1
|
||||
@@ -148,7 +135,6 @@
|
||||
#define DEFAULT_READ_AHEAD "auto"
|
||||
#define DEFAULT_UDEV_RULES 1
|
||||
#define DEFAULT_UDEV_SYNC 1
|
||||
#define DEFAULT_NOTIFY_DBUS 1
|
||||
#define DEFAULT_VERIFY_UDEV_OPERATIONS 0
|
||||
#define DEFAULT_RETRY_DEACTIVATION 1
|
||||
#define DEFAULT_ACTIVATION_CHECKS 0
|
||||
@@ -168,7 +154,6 @@
|
||||
# define DEFAULT_LOG_FACILITY LOG_USER
|
||||
#endif
|
||||
|
||||
#define DEFAULT_COMMAND_LOG_REPORT 0
|
||||
#define DEFAULT_SYSLOG 1
|
||||
#define DEFAULT_VERBOSE 0
|
||||
#define DEFAULT_SILENT 0
|
||||
@@ -216,18 +201,14 @@
|
||||
#define DEFAULT_REP_LIST_ITEM_SEPARATOR ","
|
||||
#define DEFAULT_TIME_FORMAT "%Y-%m-%d %T %z"
|
||||
|
||||
#define DEFAULT_REP_OUTPUT_FORMAT "basic"
|
||||
#define DEFAULT_COMPACT_OUTPUT_COLS ""
|
||||
|
||||
#define DEFAULT_COMMAND_LOG_SELECTION "!(log_type=status && message=success)"
|
||||
|
||||
#define DEFAULT_LVS_COLS "lv_name,vg_name,lv_attr,lv_size,pool_lv,origin,data_percent,metadata_percent,move_pv,mirror_log,copy_percent,convert_lv"
|
||||
#define DEFAULT_VGS_COLS "vg_name,pv_count,lv_count,snap_count,vg_attr,vg_size,vg_free"
|
||||
#define DEFAULT_PVS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free"
|
||||
#define DEFAULT_SEGS_COLS "lv_name,vg_name,lv_attr,stripes,segtype,seg_size"
|
||||
#define DEFAULT_PVSEGS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size"
|
||||
#define DEFAULT_DEVTYPES_COLS "devtype_name,devtype_max_partitions,devtype_description"
|
||||
#define DEFAULT_COMMAND_LOG_COLS "log_seq_num,log_type,log_context,log_object_type,log_object_name,log_object_id,log_object_group,log_object_group_id,log_message,log_errno,log_ret_code"
|
||||
|
||||
#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,lv_kernel_major,lv_kernel_minor,pool_lv,origin,data_percent,metadata_percent,move_pv,copy_percent,mirror_log,convert_lv,lv_uuid,lv_profile"
|
||||
#define DEFAULT_VGS_COLS_VERB "vg_name,vg_attr,vg_extent_size,pv_count,lv_count,snap_count,vg_size,vg_free,vg_uuid,vg_profile"
|
||||
@@ -236,25 +217,12 @@
|
||||
#define DEFAULT_PVSEGS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size,lv_name,seg_start_pe,segtype,seg_pe_ranges"
|
||||
#define DEFAULT_DEVTYPES_COLS_VERB "devtype_name,devtype_max_partitions,devtype_description"
|
||||
|
||||
#define DEFAULT_VGS_COLS_FULL "vg_all"
|
||||
#define DEFAULT_PVS_COLS_FULL "pv_all"
|
||||
#define DEFAULT_LVS_COLS_FULL "lv_all"
|
||||
#define DEFAULT_PVSEGS_COLS_FULL "pvseg_all,pv_uuid,lv_uuid"
|
||||
#define DEFAULT_SEGS_COLS_FULL "seg_all,lv_uuid"
|
||||
|
||||
#define DEFAULT_LVS_SORT "vg_name,lv_name"
|
||||
#define DEFAULT_VGS_SORT "vg_name"
|
||||
#define DEFAULT_PVS_SORT "pv_name"
|
||||
#define DEFAULT_SEGS_SORT "vg_name,lv_name,seg_start"
|
||||
#define DEFAULT_PVSEGS_SORT "pv_name,pvseg_start"
|
||||
#define DEFAULT_DEVTYPES_SORT "devtype_name"
|
||||
#define DEFAULT_COMMAND_LOG_SORT "log_seq_num"
|
||||
|
||||
#define DEFAULT_VGS_SORT_FULL "vg_name"
|
||||
#define DEFAULT_PVS_SORT_FULL "pv_name"
|
||||
#define DEFAULT_LVS_SORT_FULL "vg_name,lv_name"
|
||||
#define DEFAULT_PVSEGS_SORT_FULL "pv_uuid,pvseg_start"
|
||||
#define DEFAULT_SEGS_SORT_FULL "lv_uuid,seg_start"
|
||||
|
||||
#define DEFAULT_MIRROR_DEVICE_FAULT_POLICY "remove"
|
||||
#define DEFAULT_MIRROR_LOG_FAULT_POLICY "allocate"
|
||||
@@ -263,4 +231,6 @@
|
||||
#define DEFAULT_THIN_POOL_AUTOEXTEND_THRESHOLD 100
|
||||
#define DEFAULT_THIN_POOL_AUTOEXTEND_PERCENT 20
|
||||
|
||||
#define DEFAULT_CY_LOCK_TYPE "sanlock"
|
||||
|
||||
#endif /* _LVM_DEFAULTS_H */
|
||||
|
@@ -92,15 +92,7 @@ void str_list_del(struct dm_list *sll, const char *str)
|
||||
|
||||
dm_list_iterate_safe(slh, slht, sll)
|
||||
if (!strcmp(str, dm_list_item(slh, struct dm_str_list)->str))
|
||||
dm_list_del(slh);
|
||||
}
|
||||
|
||||
void str_list_wipe(struct dm_list *sll)
|
||||
{
|
||||
struct dm_list *slh, *slht;
|
||||
|
||||
dm_list_iterate_safe(slh, slht, sll)
|
||||
dm_list_del(slh);
|
||||
dm_list_del(slh);
|
||||
}
|
||||
|
||||
int str_list_dup(struct dm_pool *mem, struct dm_list *sllnew,
|
||||
@@ -126,8 +118,8 @@ int str_list_match_item(const struct dm_list *sll, const char *str)
|
||||
struct dm_str_list *sl;
|
||||
|
||||
dm_list_iterate_items(sl, sll)
|
||||
if (!strcmp(str, sl->str))
|
||||
return 1;
|
||||
if (!strcmp(str, sl->str))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -161,8 +153,8 @@ int str_list_lists_equal(const struct dm_list *sll, const struct dm_list *sll2)
|
||||
return 0;
|
||||
|
||||
dm_list_iterate_items(sl, sll)
|
||||
if (!str_list_match_item(sll2, sl->str))
|
||||
return 0;
|
||||
if (!str_list_match_item(sll2, sl->str))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@@ -25,7 +25,6 @@ int str_list_add_list(struct dm_pool *mem, struct dm_list *sll, struct dm_list *
|
||||
int str_list_add_no_dup_check(struct dm_pool *mem, struct dm_list *sll, const char *str);
|
||||
int str_list_add_h_no_dup_check(struct dm_pool *mem, struct dm_list *sll, const char *str);
|
||||
void str_list_del(struct dm_list *sll, const char *str);
|
||||
void str_list_wipe(struct dm_list *sll);
|
||||
int str_list_match_item(const struct dm_list *sll, const char *str);
|
||||
int str_list_match_list(const struct dm_list *sll, const struct dm_list *sll2, const char **tag_matched);
|
||||
int str_list_lists_equal(const struct dm_list *sll, const struct dm_list *sll2);
|
||||
|
@@ -17,8 +17,6 @@
|
||||
#include "btree.h"
|
||||
#include "config.h"
|
||||
#include "toolcontext.h"
|
||||
#include "dm-ioctl.h" /* for DM_UUID_LEN */
|
||||
#include "lvm-string.h" /* for LVM's UUID_PREFIX */
|
||||
|
||||
#ifdef UDEV_SYNC_SUPPORT
|
||||
#include <libudev.h>
|
||||
@@ -40,9 +38,6 @@ struct dir_list {
|
||||
static struct {
|
||||
struct dm_pool *mem;
|
||||
struct dm_hash_table *names;
|
||||
struct dm_hash_table *vgid_index;
|
||||
struct dm_hash_table *lvid_index;
|
||||
struct btree *sysfs_only_devices; /* see comments in _get_device_for_sysfs_dev_name_using_devno */
|
||||
struct btree *devices;
|
||||
struct dm_regex *preferred_names_matcher;
|
||||
const char *dev_dir;
|
||||
@@ -363,312 +358,6 @@ static int _add_alias(struct device *dev, const char *path)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _get_sysfs_value(const char *path, char *buf, size_t buf_size, int error_if_no_value)
|
||||
{
|
||||
FILE *fp;
|
||||
size_t len;
|
||||
int r = 0;
|
||||
|
||||
if (!(fp = fopen(path, "r"))) {
|
||||
log_sys_error("fopen", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!fgets(buf, buf_size, fp)) {
|
||||
log_sys_error("fgets", path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((len = strlen(buf)) && buf[len - 1] == '\n')
|
||||
buf[--len] = '\0';
|
||||
|
||||
if (!len && error_if_no_value)
|
||||
log_error("_get_sysfs_value: %s: no value", path);
|
||||
else
|
||||
r = 1;
|
||||
out:
|
||||
if (fclose(fp))
|
||||
log_sys_error("fclose", path);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _get_dm_uuid_from_sysfs(char *buf, size_t buf_size, int major, int minor)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
|
||||
if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d/dm/uuid", dm_sysfs_dir(), major, minor) < 0) {
|
||||
log_error("%d:%d: dm_snprintf failed for path to sysfs dm directory.", major, minor);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _get_sysfs_value(path, buf, buf_size, 0);
|
||||
}
|
||||
|
||||
static struct dm_list *_get_or_add_list_by_index_key(struct dm_hash_table *idx, const char *key)
|
||||
{
|
||||
struct dm_list *list;
|
||||
|
||||
if ((list = dm_hash_lookup(idx, key)))
|
||||
return list;
|
||||
|
||||
if (!(list = _zalloc(sizeof(*list)))) {
|
||||
log_error("%s: failed to allocate device list for device cache index.", key);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dm_list_init(list);
|
||||
|
||||
if (!dm_hash_insert(idx, key, list)) {
|
||||
log_error("%s: failed to insert device list to device cache index.", key);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
static struct device *_insert_sysfs_dev(dev_t devno, const char *devname)
|
||||
{
|
||||
static struct device _fake_dev = { .flags = DEV_USED_FOR_LV };
|
||||
struct stat stat0;
|
||||
char path[PATH_MAX];
|
||||
char *path_copy;
|
||||
struct device *dev;
|
||||
|
||||
if (dm_snprintf(path, sizeof(path), "%s%s", _cache.dev_dir, devname) < 0) {
|
||||
log_error("_insert_sysfs_dev: %s: dm_snprintf failed", devname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (lstat(path, &stat0) < 0) {
|
||||
/* When device node does not exist return fake entry.
|
||||
* This may happen when i.e. lvm2 device dir != /dev */
|
||||
log_debug("%s: Not available device node", path);
|
||||
return &_fake_dev;
|
||||
}
|
||||
|
||||
if (!(dev = _dev_create(devno)))
|
||||
return_NULL;
|
||||
|
||||
if (!(path_copy = dm_pool_strdup(_cache.mem, path))) {
|
||||
log_error("_insert_sysfs_dev: %s: dm_pool_strdup failed", devname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_add_alias(dev, path_copy)) {
|
||||
log_error("Couldn't add alias to dev cache.");
|
||||
_free(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!btree_insert(_cache.sysfs_only_devices, (uint32_t) devno, dev)) {
|
||||
log_error("Couldn't add device to binary tree of sysfs-only devices in dev cache.");
|
||||
_free(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
static struct device *_get_device_for_sysfs_dev_name_using_devno(const char *devname)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
char buf[PATH_MAX];
|
||||
int major, minor;
|
||||
dev_t devno;
|
||||
struct device *dev;
|
||||
|
||||
if (dm_snprintf(path, sizeof(path), "%sblock/%s/dev", dm_sysfs_dir(), devname) < 0) {
|
||||
log_error("_get_device_for_sysfs_dev_name_using_devno: %s: dm_snprintf failed", devname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_get_sysfs_value(path, buf, sizeof(buf), 1))
|
||||
return_NULL;
|
||||
|
||||
if (sscanf(buf, "%d:%d", &major, &minor) != 2) {
|
||||
log_error("_get_device_for_sysfs_dev_name_using_devno: %s: failed to get major and minor number", devname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
devno = MKDEV((dev_t)major, (dev_t)minor);
|
||||
if (!(dev = (struct device *) btree_lookup(_cache.devices, (uint32_t) devno))) {
|
||||
/*
|
||||
* If we get here, it means the device is referenced in sysfs, but it's not yet in /dev.
|
||||
* This may happen in some rare cases right after LVs get created - we sync with udev
|
||||
* (or alternatively we create /dev content ourselves) while VG lock is held. However,
|
||||
* dev scan is done without VG lock so devices may already be in sysfs, but /dev may
|
||||
* not be updated yet if we call LVM command right after LV creation. This is not a
|
||||
* problem with devtmpfs as there's at least kernel name for device in /dev as soon
|
||||
* as the sysfs item exists, but we still support environments without devtmpfs or
|
||||
* where different directory for dev nodes is used (e.g. our test suite). So track
|
||||
* such devices in _cache.sysfs_only_devices hash for the vgid/lvid check to work still.
|
||||
*/
|
||||
if (!(dev = (struct device *) btree_lookup(_cache.sysfs_only_devices, (uint32_t) devno)) &&
|
||||
!(dev = _insert_sysfs_dev(devno, devname)))
|
||||
return_NULL;
|
||||
}
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
#define NOT_LVM_UUID "-"
|
||||
|
||||
static int _get_vgid_and_lvid_for_dev(struct device *dev)
|
||||
{
|
||||
static size_t lvm_prefix_len = sizeof(UUID_PREFIX) - 1;
|
||||
static size_t lvm_uuid_len = sizeof(UUID_PREFIX) - 1 + 2 * ID_LEN;
|
||||
char uuid[DM_UUID_LEN];
|
||||
size_t uuid_len;
|
||||
|
||||
if (!_get_dm_uuid_from_sysfs(uuid, sizeof(uuid), (int) MAJOR(dev->dev), (int) MINOR(dev->dev)))
|
||||
return_0;
|
||||
|
||||
uuid_len = strlen(uuid);
|
||||
|
||||
/*
|
||||
* UUID for LV is either "LVM-<vg_uuid><lv_uuid>" or "LVM-<vg_uuid><lv_uuid>-<suffix>",
|
||||
* where vg_uuid and lv_uuid has length of ID_LEN and suffix len is not restricted
|
||||
* (only restricted by whole DM UUID max len).
|
||||
*/
|
||||
if (((uuid_len == lvm_uuid_len) ||
|
||||
((uuid_len > lvm_uuid_len) && (uuid[lvm_uuid_len] == '-'))) &&
|
||||
!strncmp(uuid, UUID_PREFIX, lvm_prefix_len)) {
|
||||
/* Separate VGID and LVID part from DM UUID. */
|
||||
if (!(dev->vgid = dm_pool_strndup(_cache.mem, uuid + lvm_prefix_len, ID_LEN)) ||
|
||||
!(dev->lvid = dm_pool_strndup(_cache.mem, uuid + lvm_prefix_len + ID_LEN, ID_LEN)))
|
||||
return_0;
|
||||
} else
|
||||
dev->vgid = dev->lvid = NOT_LVM_UUID;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _index_dev_by_vgid_and_lvid(struct device *dev)
|
||||
{
|
||||
const char *devname = dev_name(dev);
|
||||
char devpath[PATH_MAX];
|
||||
char path[PATH_MAX];
|
||||
DIR *d;
|
||||
struct dirent *dirent;
|
||||
struct device *holder_dev;
|
||||
struct dm_list *vgid_list, *lvid_list;
|
||||
struct device_list *dl_vgid, *dl_lvid;
|
||||
int r = 0;
|
||||
|
||||
if (dev->flags & DEV_USED_FOR_LV)
|
||||
/* already indexed */
|
||||
return 1;
|
||||
|
||||
/* Get holders for device. */
|
||||
if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d/holders/", dm_sysfs_dir(), (int) MAJOR(dev->dev), (int) MINOR(dev->dev)) < 0) {
|
||||
log_error("%s: dm_snprintf failed for path to holders directory.", devname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(d = opendir(path))) {
|
||||
if (errno == ENOENT) {
|
||||
log_debug("%s: path does not exist, skipping", path);
|
||||
return 1;
|
||||
}
|
||||
log_sys_error("opendir", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Iterate over device's holders and look for LVs. */
|
||||
while ((dirent = readdir(d))) {
|
||||
if (!strcmp(".", dirent->d_name) ||
|
||||
!strcmp("..", dirent->d_name))
|
||||
continue;
|
||||
|
||||
if (dm_snprintf(devpath, sizeof(devpath), "%s%s", _cache.dev_dir, dirent->d_name) == -1) {
|
||||
log_error("%s: dm_snprintf failed for holder %s device path.", devname, dirent->d_name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(holder_dev = (struct device *) dm_hash_lookup(_cache.names, devpath))) {
|
||||
/*
|
||||
* Cope with situation where canonical /<dev_dir>/<dirent->d_name>
|
||||
* does not exist, but some other node name or symlink exists in
|
||||
* non-standard environments - someone renaming the nodes or using
|
||||
* mknod with different dev names than actual kernel names.
|
||||
* This looks up struct device by major:minor pair which we get
|
||||
* by looking at /sys/block/<dirent->d_name>/dev sysfs attribute.
|
||||
*/
|
||||
if (!(holder_dev = _get_device_for_sysfs_dev_name_using_devno(dirent->d_name))) {
|
||||
log_error("%s: failed to find associated device structure for holder %s.", devname, devpath);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* We're only interested in a holder which is a DM device. */
|
||||
if (!dm_is_dm_major(MAJOR(holder_dev->dev)))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* And if it's a DM device, we're only interested in a holder which is an LVM device.
|
||||
* Get the VG UUID and LV UUID if we don't have that already.
|
||||
*/
|
||||
if (!holder_dev->vgid && !_get_vgid_and_lvid_for_dev(holder_dev))
|
||||
goto_out;
|
||||
|
||||
if (*holder_dev->vgid == *NOT_LVM_UUID)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Do not add internal LV devices to index.
|
||||
* If a device is internal, the holder has the same VG UUID as the device.
|
||||
*/
|
||||
if (dm_is_dm_major(MAJOR(dev->dev))) {
|
||||
if (!dev->vgid && !_get_vgid_and_lvid_for_dev(dev))
|
||||
goto_out;
|
||||
|
||||
if (*dev->vgid != *NOT_LVM_UUID && !strcmp(holder_dev->vgid, dev->vgid))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(vgid_list = _get_or_add_list_by_index_key(_cache.vgid_index, holder_dev->vgid)) ||
|
||||
!(lvid_list = _get_or_add_list_by_index_key(_cache.lvid_index, holder_dev->lvid)))
|
||||
goto_out;
|
||||
|
||||
/* Create dev list items for the holder device. */
|
||||
if (!(dl_vgid = _zalloc(sizeof(*dl_vgid))) ||
|
||||
!(dl_lvid = _zalloc(sizeof(*dl_lvid)))) {
|
||||
log_error("%s: failed to allocate dev list item.", devname);
|
||||
goto out;
|
||||
}
|
||||
|
||||
dl_vgid->dev = dl_lvid->dev = dev;
|
||||
|
||||
/* Add dev list item to VGID device list if it's not there already. */
|
||||
if (!(dev->flags & DEV_USED_FOR_LV))
|
||||
dm_list_add(vgid_list, &dl_vgid->list);
|
||||
|
||||
/* Add dev list item to LVID device list. */
|
||||
dm_list_add(lvid_list, &dl_lvid->list);
|
||||
|
||||
/* Mark device as used == also indexed in dev cache by VGID and LVID. */
|
||||
dev->flags |= DEV_USED_FOR_LV;
|
||||
}
|
||||
|
||||
r = 1;
|
||||
out:
|
||||
if (closedir(d))
|
||||
log_sys_error("closedir", path);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
struct dm_list *dev_cache_get_dev_list_for_vgid(const char *vgid)
|
||||
{
|
||||
return dm_hash_lookup(_cache.vgid_index, vgid);
|
||||
}
|
||||
|
||||
struct dm_list *dev_cache_get_dev_list_for_lvid(const char *lvid)
|
||||
{
|
||||
return dm_hash_lookup(_cache.lvid_index, lvid);
|
||||
}
|
||||
|
||||
/*
|
||||
* Either creates a new dev, or adds an alias to
|
||||
* an existing dev.
|
||||
@@ -689,15 +378,14 @@ static int _insert_dev(const char *path, dev_t d)
|
||||
}
|
||||
|
||||
/* is this device already registered ? */
|
||||
if (!(dev = (struct device *) btree_lookup(_cache.devices, (uint32_t) d))) {
|
||||
if (!(dev = (struct device *) btree_lookup(_cache.sysfs_only_devices, (uint32_t) d))) {
|
||||
/* create new device */
|
||||
if (loopfile) {
|
||||
if (!(dev = dev_create_file(path, NULL, NULL, 0)))
|
||||
return_0;
|
||||
} else if (!(dev = _dev_create(d)))
|
||||
if (!(dev = (struct device *) btree_lookup(_cache.devices,
|
||||
(uint32_t) d))) {
|
||||
/* create new device */
|
||||
if (loopfile) {
|
||||
if (!(dev = dev_create_file(path, NULL, NULL, 0)))
|
||||
return_0;
|
||||
}
|
||||
} else if (!(dev = _dev_create(d)))
|
||||
return_0;
|
||||
|
||||
if (!(btree_insert(_cache.devices, (uint32_t) d, dev))) {
|
||||
log_error("Couldn't insert device into binary tree.");
|
||||
@@ -805,108 +493,6 @@ static int _insert_file(const char *path)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _dev_cache_iterate_devs_for_index(void)
|
||||
{
|
||||
struct btree_iter *iter = btree_first(_cache.devices);
|
||||
struct device *dev;
|
||||
int r = 1;
|
||||
|
||||
while (iter) {
|
||||
dev = btree_get_data(iter);
|
||||
|
||||
if (!_index_dev_by_vgid_and_lvid(dev))
|
||||
r = 0;
|
||||
|
||||
iter = btree_next(iter);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _dev_cache_iterate_sysfs_for_index(const char *path)
|
||||
{
|
||||
char devname[PATH_MAX];
|
||||
DIR *d;
|
||||
struct dirent *dirent;
|
||||
int major, minor;
|
||||
dev_t devno;
|
||||
struct device *dev;
|
||||
int partial_failure = 0;
|
||||
int r = 0;
|
||||
|
||||
if (!(d = opendir(path))) {
|
||||
log_sys_error("opendir", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((dirent = readdir(d))) {
|
||||
if (!strcmp(".", dirent->d_name) ||
|
||||
!strcmp("..", dirent->d_name))
|
||||
continue;
|
||||
|
||||
if (sscanf(dirent->d_name, "%d:%d", &major, &minor) != 2) {
|
||||
log_error("_dev_cache_iterate_sysfs_for_index: %s: failed "
|
||||
"to get major and minor number", dirent->d_name);
|
||||
partial_failure = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
devno = MKDEV((dev_t)major, (dev_t)minor);
|
||||
if (!(dev = (struct device *) btree_lookup(_cache.devices, (uint32_t) devno)) &&
|
||||
!(dev = (struct device *) btree_lookup(_cache.sysfs_only_devices, (uint32_t) devno))) {
|
||||
if (!dm_device_get_name(major, minor, 1, devname, sizeof(devname)) ||
|
||||
!(dev = _insert_sysfs_dev(devno, devname))) {
|
||||
partial_failure = 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_index_dev_by_vgid_and_lvid(dev))
|
||||
partial_failure = 1;
|
||||
}
|
||||
|
||||
r = !partial_failure;
|
||||
|
||||
if (closedir(d))
|
||||
log_sys_error("closedir", path);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int dev_cache_index_devs(void)
|
||||
{
|
||||
static int sysfs_has_dev_block = -1;
|
||||
char path[PATH_MAX];
|
||||
|
||||
if (dm_snprintf(path, sizeof(path), "%sdev/block", dm_sysfs_dir()) < 0) {
|
||||
log_error("dev_cache_index_devs: dm_snprintf failed.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Skip indexing if /sys/dev/block is not available.*/
|
||||
if (sysfs_has_dev_block == -1) {
|
||||
struct stat info;
|
||||
if (stat(path, &info) == 0)
|
||||
sysfs_has_dev_block = 1;
|
||||
else {
|
||||
if (errno == ENOENT) {
|
||||
sysfs_has_dev_block = 0;
|
||||
return 1;
|
||||
} else {
|
||||
log_sys_error("stat", path);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else if (!sysfs_has_dev_block)
|
||||
return 1;
|
||||
|
||||
if (obtain_device_list_from_udev() &&
|
||||
udev_get_library_context())
|
||||
return _dev_cache_iterate_devs_for_index(); /* with udev */
|
||||
|
||||
return _dev_cache_iterate_sysfs_for_index(path);
|
||||
}
|
||||
|
||||
#ifdef UDEV_SYNC_SUPPORT
|
||||
|
||||
static int _device_in_udev_db(const dev_t d)
|
||||
@@ -1077,8 +663,6 @@ static void _full_scan(int dev_scan)
|
||||
|
||||
_insert_dirs(&_cache.dirs);
|
||||
|
||||
(void) dev_cache_index_devs();
|
||||
|
||||
dm_list_iterate_items(dl, &_cache.files)
|
||||
_insert_file(dl->dir);
|
||||
|
||||
@@ -1167,9 +751,7 @@ int dev_cache_init(struct cmd_context *cmd)
|
||||
if (!(_cache.mem = dm_pool_create("dev_cache", 10 * 1024)))
|
||||
return_0;
|
||||
|
||||
if (!(_cache.names = dm_hash_create(128)) ||
|
||||
!(_cache.vgid_index = dm_hash_create(32)) ||
|
||||
!(_cache.lvid_index = dm_hash_create(32))) {
|
||||
if (!(_cache.names = dm_hash_create(128))) {
|
||||
dm_pool_destroy(_cache.mem);
|
||||
_cache.mem = 0;
|
||||
return_0;
|
||||
@@ -1180,11 +762,6 @@ int dev_cache_init(struct cmd_context *cmd)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!(_cache.sysfs_only_devices = btree_create(_cache.mem))) {
|
||||
log_error("Couldn't create binary tree for sysfs-only devices in dev cache.");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!(_cache.dev_dir = _strdup(cmd->dev_dir))) {
|
||||
log_error("strdup dev_dir failed.");
|
||||
goto bad;
|
||||
@@ -1248,12 +825,6 @@ int dev_cache_exit(void)
|
||||
if (_cache.names)
|
||||
dm_hash_destroy(_cache.names);
|
||||
|
||||
if (_cache.vgid_index)
|
||||
dm_hash_destroy(_cache.vgid_index);
|
||||
|
||||
if (_cache.lvid_index)
|
||||
dm_hash_destroy(_cache.lvid_index);
|
||||
|
||||
memset(&_cache, 0, sizeof(_cache));
|
||||
|
||||
return (!num_open);
|
||||
@@ -1537,5 +1108,5 @@ int dev_fd(struct device *dev)
|
||||
const char *dev_name(const struct device *dev)
|
||||
{
|
||||
return (dev && dev->aliases.n) ? dm_list_item(dev->aliases.n, struct dm_str_list)->str :
|
||||
unknown_device_name();
|
||||
"unknown device";
|
||||
}
|
||||
|
@@ -31,10 +31,6 @@ struct dev_filter {
|
||||
unsigned use_count;
|
||||
};
|
||||
|
||||
int dev_cache_index_devs(void);
|
||||
struct dm_list *dev_cache_get_dev_list_for_vgid(const char *vgid);
|
||||
struct dm_list *dev_cache_get_dev_list_for_lvid(const char *lvid);
|
||||
|
||||
/*
|
||||
* The global device cache.
|
||||
*/
|
||||
|
@@ -36,9 +36,6 @@
|
||||
#define DEV_EXT_UDEV_DEVTYPE "DEVTYPE"
|
||||
#define DEV_EXT_UDEV_DEVTYPE_DISK "disk"
|
||||
|
||||
/* the list of symlinks associated with device node */
|
||||
#define DEV_EXT_UDEV_DEVLINKS "DEVLINKS"
|
||||
|
||||
/*
|
||||
* DEV_EXT_UDEV_MPATH_DEVICE_PATH is set by multipath in udev db
|
||||
* with value either 0 or 1. The same functionality as
|
||||
|
@@ -494,22 +494,11 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
|
||||
|
||||
#ifdef O_NOATIME
|
||||
/* Don't update atime on device inodes */
|
||||
if (!(dev->flags & DEV_REGULAR) && !(dev->flags & DEV_NOT_O_NOATIME))
|
||||
if (!(dev->flags & DEV_REGULAR))
|
||||
flags |= O_NOATIME;
|
||||
#endif
|
||||
|
||||
if ((dev->fd = open(name, flags, 0777)) < 0) {
|
||||
#ifdef O_NOATIME
|
||||
if ((errno == EPERM) && (flags & O_NOATIME)) {
|
||||
flags &= ~O_NOATIME;
|
||||
dev->flags |= DEV_NOT_O_NOATIME;
|
||||
if ((dev->fd = open(name, flags, 0777)) >= 0) {
|
||||
log_debug_devs("%s: Not using O_NOATIME", name);
|
||||
goto opened;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef O_DIRECT_SUPPORT
|
||||
if (direct && !(dev->flags & DEV_O_DIRECT_TESTED)) {
|
||||
flags &= ~O_DIRECT;
|
||||
@@ -524,8 +513,6 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
|
||||
log_sys_debug("open", name);
|
||||
else
|
||||
log_sys_error("open", name);
|
||||
|
||||
dev->flags |= DEV_OPEN_FAILURE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -569,7 +556,6 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
|
||||
dev->flags & DEV_OPENED_EXCL ? " O_EXCL" : "",
|
||||
dev->flags & DEV_O_DIRECT ? " O_DIRECT" : "");
|
||||
|
||||
dev->flags &= ~DEV_OPEN_FAILURE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@@ -38,8 +38,8 @@ static int _dev_has_md_magic(struct device *dev, uint64_t sb_offset)
|
||||
|
||||
/* Version 1 is little endian; version 0.90.0 is machine endian */
|
||||
if (dev_read(dev, sb_offset, sizeof(uint32_t), &md_magic) &&
|
||||
((md_magic == MD_SB_MAGIC) ||
|
||||
((MD_SB_MAGIC != xlate32(MD_SB_MAGIC)) && (md_magic == xlate32(MD_SB_MAGIC)))))
|
||||
((md_magic == xlate32(MD_SB_MAGIC)) ||
|
||||
(md_magic == MD_SB_MAGIC)))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
@@ -125,9 +125,6 @@ struct dev_types *create_dev_types(const char *proc_dir,
|
||||
if (!strncmp("emcpower", line + i, 8) && isspace(*(line + i + 8)))
|
||||
dt->emcpower_major = line_maj;
|
||||
|
||||
if (!strncmp("loop", line + i, 4) && isspace(*(line + i + 4)))
|
||||
dt->loop_major = line_maj;
|
||||
|
||||
if (!strncmp("power2", line + i, 6) && isspace(*(line + i + 6)))
|
||||
dt->power2_major = line_maj;
|
||||
|
||||
@@ -249,9 +246,6 @@ const char *dev_subsystem_name(struct dev_types *dt, struct device *dev)
|
||||
if (MAJOR(dev->dev) == dt->blkext_major)
|
||||
return "BLKEXT";
|
||||
|
||||
if (MAJOR(dev->dev) == dt->loop_major)
|
||||
return "LOOP";
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -271,38 +265,6 @@ int major_is_scsi_device(struct dev_types *dt, int major)
|
||||
return (dt->dev_type_array[major].flags & PARTITION_SCSI_DEVICE) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
static int _loop_is_with_partscan(struct device *dev)
|
||||
{
|
||||
FILE *fp;
|
||||
int partscan = 0;
|
||||
char path[PATH_MAX];
|
||||
char buffer[64];
|
||||
|
||||
if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d/loop/partscan",
|
||||
dm_sysfs_dir(),
|
||||
(int) MAJOR(dev->dev),
|
||||
(int) MINOR(dev->dev)) < 0) {
|
||||
log_warn("Sysfs path for partscan is too long.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(fp = fopen(path, "r")))
|
||||
return 0; /* not there -> no partscan */
|
||||
|
||||
if (!fgets(buffer, sizeof(buffer), fp)) {
|
||||
log_warn("Failed to read %s.", path);
|
||||
} else if (sscanf(buffer, "%d", &partscan) != 1) {
|
||||
log_warn("Failed to parse %s '%s'.", path, buffer);
|
||||
partscan = 0;
|
||||
}
|
||||
|
||||
if (fclose(fp))
|
||||
log_sys_debug("fclose", path);
|
||||
|
||||
return partscan;
|
||||
}
|
||||
|
||||
/* See linux/genhd.h and fs/partitions/msdos */
|
||||
#define PART_MAGIC 0xAA55
|
||||
#define PART_MAGIC_OFFSET UINT64_C(0x1FE)
|
||||
@@ -332,11 +294,6 @@ static int _is_partitionable(struct dev_types *dt, struct device *dev)
|
||||
if (MAJOR(dev->dev) == dt->md_major)
|
||||
return 1;
|
||||
|
||||
/* All loop devices are partitionable via blkext (as of 3.2) */
|
||||
if ((MAJOR(dev->dev) == dt->loop_major) &&
|
||||
_loop_is_with_partscan(dev))
|
||||
return 1;
|
||||
|
||||
if ((parts <= 1) || (MINOR(dev->dev) % parts))
|
||||
return 0;
|
||||
|
||||
@@ -896,12 +853,6 @@ static unsigned long _dev_topology_attribute(struct dev_types *dt,
|
||||
|
||||
result = value >> SECTOR_SHIFT;
|
||||
|
||||
if (!result && value) {
|
||||
log_warn("WARNING: Device %s: %s is %lu and is unexpectedly less than sector.",
|
||||
dev_name(dev), attribute, value);
|
||||
result = 1;
|
||||
}
|
||||
|
||||
out_close:
|
||||
if (fclose(fp))
|
||||
log_sys_debug("fclose", path);
|
||||
@@ -976,100 +927,3 @@ int dev_is_rotational(struct dev_types *dt, struct device *dev)
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UDEV_SYNC_SUPPORT
|
||||
|
||||
/*
|
||||
* Udev daemon usually has 30s timeout to process each event by default.
|
||||
* But still, that value can be changed in udev configuration and we
|
||||
* don't have libudev API to read the actual timeout value used.
|
||||
*/
|
||||
|
||||
/* FIXME: Is this long enough to wait for udev db to get initialized?
|
||||
*
|
||||
* Take also into consideration that this check is done for each
|
||||
* device that is scanned so we don't want to wait for a long time
|
||||
* if there's something wrong with udev, e.g. timeouts! With current
|
||||
* libudev API, we can't recognize whether the event processing has
|
||||
* not finished yet and it's still being processed or whether it has
|
||||
* failed already due to timeout in udev - in both cases the
|
||||
* udev_device_get_is_initialized returns 0.
|
||||
*/
|
||||
#define UDEV_DEV_IS_MPATH_COMPONENT_ITERATION_COUNT 100
|
||||
#define UDEV_DEV_IS_MPATH_COMPONENT_USLEEP 100000
|
||||
|
||||
int udev_dev_is_mpath_component(struct device *dev)
|
||||
{
|
||||
struct udev *udev_context = udev_get_library_context();
|
||||
struct udev_device *udev_device = NULL;
|
||||
const char *value;
|
||||
int initialized = 0;
|
||||
unsigned i = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (!udev_context) {
|
||||
log_warn("WARNING: No udev context available to check if device %s is multipath component.", dev_name(dev));
|
||||
return_0;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (i >= UDEV_DEV_IS_MPATH_COMPONENT_ITERATION_COUNT)
|
||||
break;
|
||||
|
||||
if (udev_device)
|
||||
udev_device_unref(udev_device);
|
||||
|
||||
if (!(udev_device = udev_device_new_from_devnum(udev_context, 'b', dev->dev))) {
|
||||
log_warn("WARNING: Failed to get udev device handler for device %s.", dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBUDEV_UDEV_DEVICE_GET_IS_INITIALIZED
|
||||
if ((initialized = udev_device_get_is_initialized(udev_device)))
|
||||
break;
|
||||
#else
|
||||
if ((initialized = (udev_device_get_property_value(udev_device, DEV_EXT_UDEV_DEVLINKS) != NULL)))
|
||||
break;
|
||||
#endif
|
||||
|
||||
log_debug("Device %s not initialized in udev database (%u/%u, %u microseconds).", dev_name(dev),
|
||||
i + 1, UDEV_DEV_IS_MPATH_COMPONENT_ITERATION_COUNT,
|
||||
i * UDEV_DEV_IS_MPATH_COMPONENT_USLEEP);
|
||||
|
||||
usleep(UDEV_DEV_IS_MPATH_COMPONENT_USLEEP);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (!initialized) {
|
||||
log_warn("WARNING: Device %s not initialized in udev database even after waiting %u microseconds.",
|
||||
dev_name(dev), i * UDEV_DEV_IS_MPATH_COMPONENT_USLEEP);
|
||||
goto out;
|
||||
}
|
||||
|
||||
value = udev_device_get_property_value(udev_device, DEV_EXT_UDEV_BLKID_TYPE);
|
||||
if (value && !strcmp(value, DEV_EXT_UDEV_BLKID_TYPE_MPATH)) {
|
||||
log_debug("Device %s is multipath component based on blkid variable in udev db (%s=\"%s\").",
|
||||
dev_name(dev), DEV_EXT_UDEV_BLKID_TYPE, value);
|
||||
ret = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
value = udev_device_get_property_value(udev_device, DEV_EXT_UDEV_MPATH_DEVICE_PATH);
|
||||
if (value && !strcmp(value, "1")) {
|
||||
log_debug("Device %s is multipath component based on multipath variable in udev db (%s=\"%s\").",
|
||||
dev_name(dev), DEV_EXT_UDEV_MPATH_DEVICE_PATH, value);
|
||||
ret = 1;
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
udev_device_unref(udev_device);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
|
||||
int udev_dev_is_mpath_component(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -21,7 +21,9 @@
|
||||
#define NUMBER_OF_MAJORS 4096
|
||||
|
||||
#ifdef __linux__
|
||||
# include "kdev_t.h"
|
||||
# define MAJOR(dev) ((dev & 0xfff00) >> 8)
|
||||
# define MINOR(dev) ((dev & 0xff) | ((dev >> 12) & 0xfff00))
|
||||
# define MKDEV(ma,mi) ((mi & 0xff) | (ma << 8) | ((mi & ~0xff) << 12))
|
||||
#else
|
||||
# define MAJOR(x) major((x))
|
||||
# define MINOR(x) minor((x))
|
||||
@@ -43,7 +45,6 @@ struct dev_types {
|
||||
int emcpower_major;
|
||||
int power2_major;
|
||||
int dasd_major;
|
||||
int loop_major;
|
||||
struct dev_type_def dev_type_array[NUMBER_OF_MAJORS];
|
||||
};
|
||||
|
||||
@@ -59,7 +60,6 @@ int dev_is_md(struct device *dev, uint64_t *sb);
|
||||
int dev_is_swap(struct device *dev, uint64_t *signature);
|
||||
int dev_is_luks(struct device *dev, uint64_t *signature);
|
||||
int dasd_is_cdl_formatted(struct device *dev);
|
||||
int udev_dev_is_mpath_component(struct device *dev);
|
||||
|
||||
/* Signature wiping. */
|
||||
#define TYPE_LVM1_MEMBER 0x001
|
||||
|
@@ -27,10 +27,6 @@
|
||||
#define DEV_OPENED_EXCL 0x00000010 /* Opened EXCL */
|
||||
#define DEV_O_DIRECT 0x00000020 /* Use O_DIRECT */
|
||||
#define DEV_O_DIRECT_TESTED 0x00000040 /* DEV_O_DIRECT is reliable */
|
||||
#define DEV_OPEN_FAILURE 0x00000080 /* Has last open failed? */
|
||||
#define DEV_USED_FOR_LV 0x00000100 /* Is device used for an LV */
|
||||
#define DEV_ASSUMED_FOR_LV 0x00000200 /* Is device assumed for an LV */
|
||||
#define DEV_NOT_O_NOATIME 0x00000400 /* Don't use O_NOATIME */
|
||||
|
||||
/*
|
||||
* Support for external device info.
|
||||
@@ -72,10 +68,7 @@ struct device {
|
||||
struct dm_list open_list;
|
||||
struct dev_ext ext;
|
||||
|
||||
const char *vgid; /* if device is an LV */
|
||||
const char *lvid; /* if device is an LV */
|
||||
|
||||
char pvid[ID_LEN + 1]; /* if device is a PV */
|
||||
char pvid[ID_LEN + 1];
|
||||
char _padding[7];
|
||||
};
|
||||
|
||||
|
@@ -121,29 +121,19 @@ const char *get_percent_string(percent_type_t def)
|
||||
return _percent_types[def];
|
||||
}
|
||||
|
||||
static const char *_lv_name(const struct logical_volume *lv)
|
||||
{
|
||||
/* Never try to display names of the internal snapshot structures. */
|
||||
if (lv_is_snapshot(lv))
|
||||
return find_cow(lv)->name;
|
||||
|
||||
return lv->name;
|
||||
}
|
||||
|
||||
const char *display_lvname(const struct logical_volume *lv)
|
||||
{
|
||||
char *name;
|
||||
const char *lv_name = _lv_name(lv);
|
||||
int r;
|
||||
|
||||
if ((lv->vg->cmd->display_lvname_idx + NAME_LEN) >= sizeof((lv->vg->cmd->display_buffer)))
|
||||
lv->vg->cmd->display_lvname_idx = 0;
|
||||
|
||||
name = lv->vg->cmd->display_buffer + lv->vg->cmd->display_lvname_idx;
|
||||
r = dm_snprintf(name, NAME_LEN, "%s/%s", lv->vg->name, lv_name);
|
||||
r = dm_snprintf(name, NAME_LEN, "%s/%s", lv->vg->name, lv->name);
|
||||
|
||||
if (r < 0) {
|
||||
log_error("Full LV name \"%s/%s\" is too long.", lv->vg->name, lv_name);
|
||||
log_error("Full LV name \"%s/%s\" is too long.", lv->vg->name, lv->name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -342,34 +332,6 @@ void lvdisplay_colons(const struct logical_volume *lv)
|
||||
inkernel ? info.major : -1, inkernel ? info.minor : -1);
|
||||
}
|
||||
|
||||
static int _lvdisplay_historical_full(struct cmd_context *cmd,
|
||||
const struct logical_volume *lv)
|
||||
{
|
||||
char uuid[64] __attribute__((aligned(8)));
|
||||
int lvm1compat = find_config_tree_bool(cmd, global_lvdisplay_shows_full_device_path_CFG, NULL);
|
||||
struct historical_logical_volume *hlv = lv->this_glv->historical;
|
||||
|
||||
if (!id_write_format(&hlv->lvid.id[1], uuid, sizeof(uuid)))
|
||||
return_0;
|
||||
|
||||
log_print("--- Historical Logical volume ---");
|
||||
|
||||
if (lvm1compat)
|
||||
/* /dev/vgname/lvname doen't actually exist for historical devices */
|
||||
log_print("LV Name %s%s/%s",
|
||||
hlv->vg->cmd->dev_dir, hlv->vg->name, hlv->name);
|
||||
else
|
||||
log_print("LV Name %s%s", HISTORICAL_LV_PREFIX, hlv->name);
|
||||
|
||||
log_print("VG Name %s", hlv->vg->name);
|
||||
log_print("LV UUID %s", uuid);
|
||||
log_print("LV Creation time %s", lv_creation_time_dup(cmd->mem, lv, 1));
|
||||
log_print("LV Removal time %s", lv_removal_time_dup(cmd->mem, lv, 1));
|
||||
|
||||
log_print(" ");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lvdisplay_full(struct cmd_context *cmd,
|
||||
const struct logical_volume *lv,
|
||||
void *handle __attribute__((unused)))
|
||||
@@ -387,9 +349,6 @@ int lvdisplay_full(struct cmd_context *cmd,
|
||||
int thin_active = 0;
|
||||
dm_percent_t thin_percent;
|
||||
|
||||
if (lv_is_historical(lv))
|
||||
return _lvdisplay_historical_full(cmd, lv);
|
||||
|
||||
if (!id_write_format(&lv->lvid.id[1], uuid, sizeof(uuid)))
|
||||
return_0;
|
||||
|
||||
@@ -424,7 +383,7 @@ int lvdisplay_full(struct cmd_context *cmd,
|
||||
log_print("LV UUID %s", uuid);
|
||||
log_print("LV Write Access %s", access_str);
|
||||
log_print("LV Creation host, time %s, %s",
|
||||
lv_host_dup(cmd->mem, lv), lv_creation_time_dup(cmd->mem, lv, 1));
|
||||
lv_host_dup(cmd->mem, lv), lv_time_dup(cmd->mem, lv, 1));
|
||||
|
||||
if (lv_is_origin(lv)) {
|
||||
log_print("LV snapshot status source of");
|
||||
@@ -831,102 +790,50 @@ void display_name_error(name_error_t name_error)
|
||||
* Prompt for y or n from stdin.
|
||||
* Defaults to 'no' in silent mode.
|
||||
* All callers should support --yes and/or --force to override this.
|
||||
*
|
||||
* Accepted are either _yes[] or _no[] strings or just their outset.
|
||||
* When running without 'tty' stdin is printed to stderr.
|
||||
* 'Yes' is accepted ONLY with '\n'.
|
||||
*/
|
||||
char yes_no_prompt(const char *prompt, ...)
|
||||
{
|
||||
/* Lowercase Yes/No strings */
|
||||
static const char _yes[] = "yes";
|
||||
static const char _no[] = "no";
|
||||
const char *answer = NULL;
|
||||
int c = silent_mode() ? EOF : 0;
|
||||
int i = 0, ret = 0, sig = 0;
|
||||
char buf[12];
|
||||
int c = 0, ret = 0, cb = 0;
|
||||
va_list ap;
|
||||
|
||||
sigint_allow();
|
||||
|
||||
for (;;) {
|
||||
if (!ret) {
|
||||
/* Show prompt */
|
||||
do {
|
||||
if (c == '\n' || !c) {
|
||||
va_start(ap, prompt);
|
||||
vfprintf(stderr, prompt, ap);
|
||||
va_end(ap);
|
||||
fflush(stderr);
|
||||
|
||||
if (c == EOF)
|
||||
if (silent_mode()) {
|
||||
fputc('n', stderr);
|
||||
ret = 'n';
|
||||
break;
|
||||
|
||||
i = 0;
|
||||
answer = NULL;
|
||||
}
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
nextchar:
|
||||
if ((sig = sigint_caught()))
|
||||
break; /* Check if already interrupted before getchar() */
|
||||
|
||||
if ((c = getchar()) == EOF) {
|
||||
/* SIGNAL or no chars on stdin (missing '\n') or ^D */
|
||||
if (!i)
|
||||
break; /* Just shown prompt,-> print [n]\n */
|
||||
|
||||
goto invalid; /* Note: c holds EOF */
|
||||
ret = 'n'; /* SIGINT */
|
||||
cb = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((i < (sizeof(buf) - 4)) && isprint(c))
|
||||
buf[i++] = c;
|
||||
|
||||
c = tolower(c);
|
||||
|
||||
if ((ret > 0) && (c == answer[0]))
|
||||
answer++; /* Matching, next char */
|
||||
else if (c == '\n') {
|
||||
if (feof(stdin))
|
||||
fputc('\n', stderr);
|
||||
if (ret > 0)
|
||||
break; /* Answered */
|
||||
invalid:
|
||||
if (i >= (sizeof(buf) - 4)) {
|
||||
/* '...' for missing input */
|
||||
i = sizeof(buf) - 1;
|
||||
buf[i - 1] = buf[i - 2] = buf[i - 3] = '.';
|
||||
}
|
||||
buf[i] = 0;
|
||||
log_warn("WARNING: Invalid input '%s'.", buf);
|
||||
ret = 0; /* Otherwise refresh prompt */
|
||||
} else if (!ret && (c == _yes[0])) {
|
||||
ret = 'y';
|
||||
answer = _yes + 1; /* Expecting 'Yes' */
|
||||
} else if (!ret && (c == _no[0])) {
|
||||
ret = 'n';
|
||||
answer = _no + 1; /* Expecting 'No' */
|
||||
} else if (!ret && isspace(c)) {
|
||||
/* Ignore any whitespace before */
|
||||
--i;
|
||||
goto nextchar;
|
||||
} else if ((ret > 0) && isspace(c)) {
|
||||
/* Ignore any whitespace after */
|
||||
while (*answer)
|
||||
answer++; /* jump to end-of-word */
|
||||
} else
|
||||
ret = -1; /* Read till '\n' and refresh */
|
||||
}
|
||||
if ((c == 'y') || (c == 'n')) {
|
||||
/* If both 'y' and 'n' given, begin again. */
|
||||
if (ret && c != ret)
|
||||
ret = -1;
|
||||
else
|
||||
ret = c;
|
||||
}
|
||||
} while (ret < 1 || c != '\n');
|
||||
|
||||
sigint_restore();
|
||||
|
||||
/* For other then Yes answer check there is really no interrupt */
|
||||
if (sig || sigint_caught()) {
|
||||
stack;
|
||||
ret = 'n';
|
||||
} else if (c == EOF) {
|
||||
fputs("[n]\n", stderr);
|
||||
ret = 'n';
|
||||
} else
|
||||
/* Not knowing if it's terminal, makes this hard.... */
|
||||
log_verbose("Accepted input: [%c]", ret);
|
||||
if (cb && !sigint_caught())
|
||||
fputc(ret, stderr);
|
||||
|
||||
if (c != '\n')
|
||||
fputc('\n', stderr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@@ -55,8 +55,8 @@ static int _errseg_target_present(struct cmd_context *cmd,
|
||||
/* Reported truncated in older kernels */
|
||||
if (!_errseg_checked) {
|
||||
_errseg_checked = 1;
|
||||
_errseg_present = target_present(cmd, TARGET_NAME_ERROR, 0) ||
|
||||
target_present(cmd, TARGET_NAME_ERROR_OLD, 0);
|
||||
_errseg_present = target_present(cmd, "error", 0) ||
|
||||
target_present(cmd, "erro", 0);
|
||||
}
|
||||
|
||||
return _errseg_present;
|
||||
@@ -66,7 +66,7 @@ static int _errseg_modules_needed(struct dm_pool *mem,
|
||||
const struct lv_segment *seg __attribute__((unused)),
|
||||
struct dm_list *modules)
|
||||
{
|
||||
if (!str_list_add(mem, modules, MODULE_NAME_ERROR)) {
|
||||
if (!str_list_add(mem, modules, "error")) {
|
||||
log_error("error module string list allocation failed");
|
||||
return 0;
|
||||
}
|
||||
|
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2006 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
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
#include "filter.h"
|
||||
|
||||
static DM_LIST_INIT(_allow_devs);
|
||||
|
||||
int internal_filter_allow(struct dm_pool *mem, struct device *dev)
|
||||
{
|
||||
struct device_list *devl;
|
||||
|
||||
if (!(devl = dm_pool_alloc(mem, sizeof(*devl)))) {
|
||||
log_error("device_list element allocation failed");
|
||||
return 0;
|
||||
}
|
||||
devl->dev = dev;
|
||||
|
||||
dm_list_add(&_allow_devs, &devl->list);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void internal_filter_clear(void)
|
||||
{
|
||||
dm_list_init(&_allow_devs);
|
||||
}
|
||||
|
||||
static int _passes_internal(struct dev_filter *f __attribute__((unused)),
|
||||
struct device *dev)
|
||||
{
|
||||
struct device_list *devl;
|
||||
|
||||
if (!internal_filtering())
|
||||
return 1;
|
||||
|
||||
dm_list_iterate_items(devl, &_allow_devs) {
|
||||
if (devl->dev == dev)
|
||||
return 1;
|
||||
}
|
||||
|
||||
log_debug_devs("%s: Skipping for internal filtering.", dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _destroy(struct dev_filter *f)
|
||||
{
|
||||
if (f->use_count)
|
||||
log_error(INTERNAL_ERROR "Destroying internal filter while in use %u times.", f->use_count);
|
||||
|
||||
dm_free(f);
|
||||
}
|
||||
|
||||
struct dev_filter *internal_filter_create(void)
|
||||
{
|
||||
struct dev_filter *f;
|
||||
|
||||
if (!(f = dm_zalloc(sizeof(*f)))) {
|
||||
log_error("md filter allocation failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f->passes_filter = _passes_internal;
|
||||
f->destroy = _destroy;
|
||||
f->use_count = 0;
|
||||
|
||||
log_debug_devs("internal filter initialised.");
|
||||
|
||||
return f;
|
||||
}
|
||||
|
@@ -129,8 +129,6 @@ int persistent_filter_load(struct dev_filter *f, struct dm_config_tree **cft_out
|
||||
if (dm_hash_get_num_entries(pf->devices)) {
|
||||
/* We populated dev_cache ourselves */
|
||||
dev_cache_scan(0);
|
||||
if (!dev_cache_index_devs())
|
||||
stack;
|
||||
r = 1;
|
||||
}
|
||||
|
||||
|
@@ -17,7 +17,6 @@
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
#include <sys/sysmacros.h>
|
||||
#include <dirent.h>
|
||||
|
||||
static int _locate_sysfs_blocks(const char *sysfs_dir, char *path, size_t len,
|
||||
|
@@ -32,10 +32,6 @@ struct dev_filter *persistent_filter_create(struct dev_types *dt,
|
||||
const char *file);
|
||||
struct dev_filter *sysfs_filter_create(void);
|
||||
|
||||
struct dev_filter *internal_filter_create(void);
|
||||
int internal_filter_allow(struct dm_pool *mem, struct device *dev);
|
||||
void internal_filter_clear(void);
|
||||
|
||||
/*
|
||||
* patterns must be an array of strings of the form:
|
||||
* [ra]<sep><regex><sep>, eg,
|
||||
|
@@ -345,7 +345,10 @@ static int _format1_pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
}
|
||||
|
||||
static int _format1_pv_initialise(const struct format_type * fmt,
|
||||
struct pv_create_args *pva,
|
||||
int64_t label_sector __attribute__((unused)),
|
||||
unsigned long data_alignment __attribute__((unused)),
|
||||
unsigned long data_alignment_offset __attribute__((unused)),
|
||||
struct pvcreate_restorable_params *rp,
|
||||
struct physical_volume * pv)
|
||||
{
|
||||
if (pv->size > MAX_PV_SIZE)
|
||||
@@ -357,18 +360,18 @@ static int _format1_pv_initialise(const struct format_type * fmt,
|
||||
}
|
||||
|
||||
/* Nothing more to do if extent size isn't provided */
|
||||
if (!pva->extent_size)
|
||||
if (!rp->extent_size)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* This works out pe_start and pe_count.
|
||||
*/
|
||||
if (!calculate_extent_count(pv, pva->extent_size, pva->extent_count, pva->pe_start))
|
||||
if (!calculate_extent_count(pv, rp->extent_size, rp->extent_count, rp->pe_start))
|
||||
return_0;
|
||||
|
||||
/* Retain existing extent locations exactly */
|
||||
if (((pva->pe_start || pva->extent_count) && (pva->pe_start != pv->pe_start)) ||
|
||||
(pva->extent_count && (pva->extent_count != pv->pe_count))) {
|
||||
if (((rp->pe_start || rp->extent_count) && (rp->pe_start != pv->pe_start)) ||
|
||||
(rp->extent_count && (rp->extent_count != pv->pe_count))) {
|
||||
log_error("Metadata would overwrite physical extents");
|
||||
return 0;
|
||||
}
|
||||
@@ -380,15 +383,16 @@ static int _format1_pv_setup(const struct format_type *fmt,
|
||||
struct physical_volume *pv,
|
||||
struct volume_group *vg)
|
||||
{
|
||||
struct pv_create_args pva = { .id = {{0}},
|
||||
.idp = NULL,
|
||||
.ba_start = 0,
|
||||
.ba_size = 0,
|
||||
.pe_start = 0,
|
||||
.extent_count = 0,
|
||||
.extent_size = vg->extent_size};
|
||||
struct pvcreate_restorable_params rp = {.restorefile = NULL,
|
||||
.id = {{0}},
|
||||
.idp = NULL,
|
||||
.ba_start = 0,
|
||||
.ba_size = 0,
|
||||
.pe_start = 0,
|
||||
.extent_count = 0,
|
||||
.extent_size = vg->extent_size};
|
||||
|
||||
return _format1_pv_initialise(fmt, &pva, pv);
|
||||
return _format1_pv_initialise(fmt, -1, 0, 0, &rp, pv);
|
||||
}
|
||||
|
||||
static int _format1_lv_setup(struct format_instance *fid, struct logical_volume *lv)
|
||||
|
@@ -60,8 +60,7 @@ static void _add_pl_to_list(struct cmd_context *cmd, struct dm_list *head, struc
|
||||
if (id_equal(&data->pv_uuid, &pl->pv_uuid)) {
|
||||
char uuid[ID_LEN + 7] __attribute__((aligned(8)));
|
||||
|
||||
if (!id_write_format(&pl->pv_uuid, uuid, ID_LEN + 7))
|
||||
stack;
|
||||
id_write_format(&pl->pv_uuid, uuid, ID_LEN + 7);
|
||||
|
||||
if (!dev_subsystem_part_major(cmd->dev_types, data->dev)) {
|
||||
log_very_verbose("Ignoring duplicate PV %s on "
|
||||
@@ -91,13 +90,11 @@ int read_pool_label(struct pool_list *pl, struct labeller *l,
|
||||
pool_label_in(pd, buf);
|
||||
|
||||
get_pool_pv_uuid(&pvid, pd);
|
||||
if (!id_write_format(&pvid, uuid, ID_LEN + 7))
|
||||
stack;
|
||||
id_write_format(&pvid, uuid, ID_LEN + 7);
|
||||
log_debug_metadata("Calculated uuid %s for %s", uuid, dev_name(dev));
|
||||
|
||||
get_pool_vg_uuid(&vgid, pd);
|
||||
if (!id_write_format(&vgid, uuid, ID_LEN + 7))
|
||||
stack;
|
||||
id_write_format(&vgid, uuid, ID_LEN + 7);
|
||||
log_debug_metadata("Calculated uuid %s for %s", uuid, pd->pl_pool_name);
|
||||
|
||||
if (!(info = lvmcache_add(l, (char *) &pvid, dev, pd->pl_pool_name,
|
||||
|
@@ -166,7 +166,10 @@ bad:
|
||||
}
|
||||
|
||||
static int _pool_pv_initialise(const struct format_type *fmt __attribute__((unused)),
|
||||
struct pv_create_args *pva __attribute__((unused)),
|
||||
int64_t label_sector __attribute__((unused)),
|
||||
unsigned long data_alignment __attribute__((unused)),
|
||||
unsigned long data_alignment_offset __attribute__((unused)),
|
||||
struct pvcreate_restorable_params *rp __attribute__((unused)),
|
||||
struct physical_volume *pv __attribute__((unused)))
|
||||
{
|
||||
return 1;
|
||||
|
@@ -181,7 +181,7 @@ static int _add_stripe_seg(struct dm_pool *mem,
|
||||
unsigned j;
|
||||
uint32_t area_len;
|
||||
|
||||
if (!is_power_of_2(usp->striping)) {
|
||||
if (usp->striping & (usp->striping - 1)) {
|
||||
log_error("Stripe size must be a power of 2");
|
||||
return 0;
|
||||
}
|
||||
|
@@ -329,22 +329,17 @@ struct volume_group *backup_read_vg(struct cmd_context *cmd,
|
||||
return vg;
|
||||
}
|
||||
|
||||
static int _restore_vg_should_write_pv(struct physical_volume *pv, int do_pvcreate)
|
||||
static int _restore_vg_should_write_pv(struct physical_volume *pv, struct pvcreate_params *pp)
|
||||
{
|
||||
struct lvmcache_info *info;
|
||||
|
||||
if (do_pvcreate)
|
||||
if (pp)
|
||||
return 1;
|
||||
|
||||
if (!(pv->fmt->features & FMT_PV_FLAGS))
|
||||
return 0;
|
||||
|
||||
if (!pv->dev) {
|
||||
log_error("Failed to find device for PV.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(info = lvmcache_info_from_pvid(pv->dev->pvid, pv->dev, 0))) {
|
||||
if (!(info = lvmcache_info_from_pvid(pv->dev->pvid, 0))) {
|
||||
log_error("Failed to find cached info for PV %s.", pv_dev_name(pv));
|
||||
return -1;
|
||||
}
|
||||
@@ -364,15 +359,16 @@ static int _restore_vg_should_write_pv(struct physical_volume *pv, int do_pvcrea
|
||||
|
||||
/* ORPHAN and VG locks held before calling this */
|
||||
int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg,
|
||||
int do_pvcreate, struct pv_create_args *pva)
|
||||
struct pvcreate_params *pp, int drop_lvmetad)
|
||||
{
|
||||
struct dm_list new_pvs;
|
||||
struct pv_list *pvl, *new_pvl;
|
||||
struct physical_volume *existing_pv, *pv;
|
||||
struct dm_list *pvs = &vg->pvs;
|
||||
struct dm_list *pvs = &vg->pvs;;
|
||||
struct format_instance *fid;
|
||||
struct format_instance_ctx fic;
|
||||
int should_write_pv;
|
||||
struct pv_to_write *pvw;
|
||||
uint32_t tmp_extent_size;
|
||||
|
||||
/*
|
||||
@@ -381,20 +377,25 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg,
|
||||
*/
|
||||
|
||||
/* Prepare new PVs if needed. */
|
||||
if (do_pvcreate) {
|
||||
if (pp) {
|
||||
dm_list_init(&new_pvs);
|
||||
|
||||
dm_list_iterate_items(pvl, &vg->pvs) {
|
||||
existing_pv = pvl->pv;
|
||||
|
||||
pva->id = existing_pv->id;
|
||||
pva->idp = &pva->id;
|
||||
pva->pe_start = pv_pe_start(existing_pv);
|
||||
pva->extent_count = pv_pe_count(existing_pv);
|
||||
pva->extent_size = pv_pe_size(existing_pv);
|
||||
pp->rp.id = existing_pv->id;
|
||||
pp->rp.idp = &pp->rp.id;
|
||||
pp->rp.pe_start = pv_pe_start(existing_pv);
|
||||
pp->rp.extent_count = pv_pe_count(existing_pv);
|
||||
pp->rp.extent_size = pv_pe_size(existing_pv);
|
||||
/* pe_end = pv_pe_count(existing_pv) * pv_pe_size(existing_pv) + pe_start - 1 */
|
||||
|
||||
if (!(pv = pv_create(cmd, pv_dev(existing_pv), pva))) {
|
||||
if (!(pv = pv_create(cmd, pv_dev(existing_pv),
|
||||
0, 0, 0,
|
||||
pp->labelsector,
|
||||
pp->pvmetadatacopies,
|
||||
pp->pvmetadatasize,
|
||||
0, &pp->rp))) {
|
||||
log_error("Failed to setup physical volume \"%s\".",
|
||||
pv_dev_name(existing_pv));
|
||||
return 0;
|
||||
@@ -407,7 +408,6 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg,
|
||||
pv_dev_name(pvl->pv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
new_pvl->pv = pv;
|
||||
dm_list_add(&new_pvs, &new_pvl->list);
|
||||
|
||||
@@ -427,7 +427,7 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (do_pvcreate) {
|
||||
if (pp) {
|
||||
log_verbose("Deleting existing metadata for VG %s.", vg->name);
|
||||
if (!vg_remove_mdas(vg)) {
|
||||
cmd->fmt->ops->destroy_instance(fid);
|
||||
@@ -449,18 +449,23 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg,
|
||||
|
||||
/* Add any metadata areas on the PVs */
|
||||
dm_list_iterate_items(pvl, pvs) {
|
||||
if ((should_write_pv = _restore_vg_should_write_pv(pvl->pv, do_pvcreate)) < 0)
|
||||
if ((should_write_pv = _restore_vg_should_write_pv(pvl->pv, pp)) < 0)
|
||||
return_0;
|
||||
|
||||
if (should_write_pv) {
|
||||
if (!(new_pvl = dm_pool_zalloc(vg->vgmem, sizeof(*new_pvl)))) {
|
||||
if (!(pvw = dm_pool_zalloc(vg->vgmem, sizeof(*pvw)))) {
|
||||
log_error("Failed to allocate structure for scheduled "
|
||||
"writing of PV '%s'.", pv_dev_name(pvl->pv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
new_pvl->pv = pvl->pv;
|
||||
dm_list_add(&vg->pv_write_list, &new_pvl->list);
|
||||
if (pp) {
|
||||
pvw->new_pv = 1;
|
||||
pvw->pp = pp;
|
||||
}
|
||||
|
||||
pvw->pv = pvl->pv;
|
||||
dm_list_add(&vg->pvs_to_write, &pvw->list);
|
||||
}
|
||||
|
||||
/* Add any metadata areas on the PV. */
|
||||
@@ -475,36 +480,19 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg,
|
||||
vg->extent_size = tmp_extent_size;
|
||||
}
|
||||
|
||||
if (do_pvcreate) {
|
||||
dm_list_iterate_items(pvl, &vg->pv_write_list) {
|
||||
struct device *dev = pv_dev(pvl->pv);
|
||||
const char *pv_name = dev_name(dev);
|
||||
|
||||
if (!label_remove(dev)) {
|
||||
log_error("Failed to wipe existing label on %s", pv_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_verbose("Zeroing start of device %s", pv_name);
|
||||
if (!dev_open_quiet(dev)) {
|
||||
log_error("%s not opened: device not zeroed", pv_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dev_set(dev, UINT64_C(0), (size_t) 2048, 0)) {
|
||||
log_error("%s not wiped: aborting", pv_name);
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
}
|
||||
}
|
||||
|
||||
if (!vg_write(vg))
|
||||
return_0;
|
||||
|
||||
if (drop_lvmetad && lvmetad_active()) {
|
||||
struct volume_group *vg_lvmetad = lvmetad_vg_lookup(cmd, vg->name, NULL);
|
||||
if (vg_lvmetad) {
|
||||
/* FIXME Cope with failure to update lvmetad */
|
||||
if (!lvmetad_vg_remove(vg_lvmetad))
|
||||
stack;
|
||||
release_vg(vg_lvmetad);
|
||||
}
|
||||
}
|
||||
|
||||
if (!vg_commit(vg))
|
||||
return_0;
|
||||
|
||||
@@ -543,7 +531,7 @@ int backup_restore_from_file(struct cmd_context *cmd, const char *vg_name,
|
||||
|
||||
missing_pvs = vg_missing_pv_count(vg);
|
||||
if (missing_pvs == 0)
|
||||
r = backup_restore_vg(cmd, vg, 0, NULL);
|
||||
r = backup_restore_vg(cmd, vg, NULL, 1);
|
||||
else
|
||||
log_error("Cannot restore Volume Group %s with %i PVs "
|
||||
"marked as missing.", vg->name, missing_pvs);
|
||||
|
@@ -51,10 +51,8 @@ int backup_remove(struct cmd_context *cmd, const char *vg_name);
|
||||
|
||||
struct volume_group *backup_read_vg(struct cmd_context *cmd,
|
||||
const char *vg_name, const char *file);
|
||||
|
||||
int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg,
|
||||
int do_pvcreate, struct pv_create_args *pva);
|
||||
|
||||
struct pvcreate_params *pp, int drop_lvmetad);
|
||||
int backup_restore_from_file(struct cmd_context *cmd, const char *vg_name,
|
||||
const char *file, int force);
|
||||
int backup_restore(struct cmd_context *cmd, const char *vg_name, int force);
|
||||
|
@@ -22,7 +22,6 @@
|
||||
#include "text_export.h"
|
||||
#include "lvm-version.h"
|
||||
#include "toolcontext.h"
|
||||
#include "config-util.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
@@ -622,7 +621,6 @@ int out_areas(struct formatter *f, const struct lv_segment *seg,
|
||||
(s == seg->area_count - 1) ? "" : ",");
|
||||
break;
|
||||
case AREA_LV:
|
||||
/* FIXME This helper code should be target-independent! Check for metadata LV property. */
|
||||
if (!(seg->status & RAID)) {
|
||||
outf(f, "\"%s\", %u%s",
|
||||
seg_lv(seg, s)->name,
|
||||
@@ -632,19 +630,15 @@ int out_areas(struct formatter *f, const struct lv_segment *seg,
|
||||
}
|
||||
|
||||
/* RAID devices are laid-out in metadata/data pairs */
|
||||
/* FIXME Validation should be elsewhere, not here! */
|
||||
if (!lv_is_raid_image(seg_lv(seg, s)) ||
|
||||
(seg->meta_areas && seg_metalv(seg, s) && !lv_is_raid_metadata(seg_metalv(seg, s)))) {
|
||||
!lv_is_raid_metadata(seg_metalv(seg, s))) {
|
||||
log_error("RAID segment has non-RAID areas");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (seg->meta_areas && seg_metalv(seg,s))
|
||||
outf(f, "\"%s\", \"%s\"%s",
|
||||
(seg->meta_areas && seg_metalv(seg, s)) ? seg_metalv(seg, s)->name : "",
|
||||
seg_lv(seg, s)->name, (s == seg->area_count - 1) ? "" : ",");
|
||||
else
|
||||
outf(f, "\"%s\"%s", seg_lv(seg, s)->name, (s == seg->area_count - 1) ? "" : ",");
|
||||
outf(f, "\"%s\", \"%s\"%s",
|
||||
seg_metalv(seg, s)->name, seg_lv(seg, s)->name,
|
||||
(s == seg->area_count - 1) ? "" : ",");
|
||||
|
||||
break;
|
||||
case AREA_UNASSIGNED:
|
||||
@@ -657,30 +651,13 @@ int out_areas(struct formatter *f, const struct lv_segment *seg,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _print_timestamp(struct formatter *f,
|
||||
const char *name, time_t ts,
|
||||
char *buf, size_t buf_size)
|
||||
{
|
||||
struct tm *local_tm;
|
||||
|
||||
if (ts) {
|
||||
strncpy(buf, "# ", buf_size);
|
||||
if (!(local_tm = localtime(&ts)) ||
|
||||
!strftime(buf + 2, buf_size - 2,
|
||||
"%Y-%m-%d %T %z", local_tm))
|
||||
buf[0] = 0;
|
||||
|
||||
outfc(f, buf, "%s = %" PRIu64, name, (uint64_t) ts);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _print_lv(struct formatter *f, struct logical_volume *lv)
|
||||
{
|
||||
struct lv_segment *seg;
|
||||
char buffer[4096];
|
||||
int seg_count;
|
||||
struct tm *local_tm;
|
||||
time_t ts;
|
||||
uint64_t status = lv->status;
|
||||
|
||||
outnl(f);
|
||||
@@ -709,10 +686,16 @@ static int _print_lv(struct formatter *f, struct logical_volume *lv)
|
||||
return_0;
|
||||
|
||||
if (lv->timestamp) {
|
||||
if (!_print_timestamp(f, "creation_time", lv->timestamp,
|
||||
buffer, sizeof(buffer)))
|
||||
return_0;
|
||||
ts = (time_t)lv->timestamp;
|
||||
strncpy(buffer, "# ", sizeof(buffer));
|
||||
if (!(local_tm = localtime(&ts)) ||
|
||||
!strftime(buffer + 2, sizeof(buffer) - 2,
|
||||
"%Y-%m-%d %T %z", local_tm))
|
||||
buffer[0] = 0;
|
||||
|
||||
outf(f, "creation_host = \"%s\"", lv->hostname);
|
||||
outfc(f, buffer, "creation_time = %" PRIu64,
|
||||
lv->timestamp);
|
||||
}
|
||||
|
||||
if (lv->lock_args)
|
||||
@@ -791,127 +774,6 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _alloc_printed_indirect_descendants(struct dm_list *indirect_glvs, char **buffer)
|
||||
{
|
||||
struct glv_list *user_glvl;
|
||||
size_t buf_size = 0;
|
||||
int first = 1;
|
||||
char *buf;
|
||||
|
||||
*buffer = NULL;
|
||||
|
||||
dm_list_iterate_items(user_glvl, indirect_glvs) {
|
||||
if (user_glvl->glv->is_historical)
|
||||
continue;
|
||||
/* '"' + name + '"' + ',' + ' ' */
|
||||
buf_size += strlen(user_glvl->glv->live->name) + 4;
|
||||
}
|
||||
|
||||
if (!buf_size)
|
||||
return 1;
|
||||
|
||||
/* '[' + ']' + '\0' */
|
||||
buf_size += 3;
|
||||
|
||||
if (!(*buffer = dm_malloc(buf_size))) {
|
||||
log_error("Could not allocate memory for ancestor list buffer.");
|
||||
return 0;
|
||||
}
|
||||
buf = *buffer;
|
||||
|
||||
if (!emit_to_buffer(&buf, &buf_size, "["))
|
||||
goto_bad;
|
||||
|
||||
dm_list_iterate_items(user_glvl, indirect_glvs) {
|
||||
if (user_glvl->glv->is_historical)
|
||||
continue;
|
||||
if (!first) {
|
||||
if (!emit_to_buffer(&buf, &buf_size, ", "))
|
||||
goto_bad;
|
||||
} else
|
||||
first = 0;
|
||||
|
||||
if (!emit_to_buffer(&buf, &buf_size, "\"%s\"", user_glvl->glv->live->name))
|
||||
goto_bad;
|
||||
}
|
||||
|
||||
if (!emit_to_buffer(&buf, &buf_size, "]"))
|
||||
goto_bad;
|
||||
|
||||
return 1;
|
||||
bad:
|
||||
if (*buffer) {
|
||||
dm_free(*buffer);
|
||||
*buffer = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _print_historical_lv(struct formatter *f, struct historical_logical_volume *hlv)
|
||||
{
|
||||
char buffer[40];
|
||||
char *descendants_buffer = NULL;
|
||||
int r = 0;
|
||||
|
||||
if (!id_write_format(&hlv->lvid.id[1], buffer, sizeof(buffer)))
|
||||
goto_out;
|
||||
|
||||
if (!_alloc_printed_indirect_descendants(&hlv->indirect_glvs, &descendants_buffer))
|
||||
goto_out;
|
||||
|
||||
outnlgo(f);
|
||||
outfgo(f, "%s {", hlv->name);
|
||||
_inc_indent(f);
|
||||
|
||||
outfgo(f, "id = \"%s\"", buffer);
|
||||
|
||||
if (!_print_timestamp(f, "creation_time", hlv->timestamp, buffer, sizeof(buffer)))
|
||||
goto_out;
|
||||
|
||||
if (!_print_timestamp(f, "removal_time", hlv->timestamp_removed, buffer, sizeof(buffer)))
|
||||
goto_out;
|
||||
|
||||
if (hlv->indirect_origin) {
|
||||
if (hlv->indirect_origin->is_historical)
|
||||
outfgo(f, "origin = \"%s%s\"", HISTORICAL_LV_PREFIX, hlv->indirect_origin->historical->name);
|
||||
else
|
||||
outfgo(f, "origin = \"%s\"", hlv->indirect_origin->live->name);
|
||||
}
|
||||
|
||||
if (descendants_buffer)
|
||||
outfgo(f, "descendants = %s", descendants_buffer);
|
||||
|
||||
_dec_indent(f);
|
||||
outfgo(f, "}");
|
||||
|
||||
r = 1;
|
||||
out:
|
||||
if (descendants_buffer)
|
||||
dm_free(descendants_buffer);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _print_historical_lvs(struct formatter *f, struct volume_group *vg)
|
||||
{
|
||||
struct glv_list *glvl;
|
||||
|
||||
if (dm_list_empty(&vg->historical_lvs))
|
||||
return 1;
|
||||
|
||||
outf(f, "historical_logical_volumes {");
|
||||
_inc_indent(f);
|
||||
|
||||
dm_list_iterate_items(glvl, &vg->historical_lvs) {
|
||||
if (!_print_historical_lv(f, glvl->glv->historical))
|
||||
return_0;
|
||||
}
|
||||
|
||||
_dec_indent(f);
|
||||
outf(f, "}");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* In the text format we refer to pv's as 'pv1',
|
||||
* 'pv2' etc. This function builds a hash table
|
||||
@@ -978,10 +840,6 @@ static int _text_vg_export(struct formatter *f,
|
||||
if (!_print_lvs(f, vg))
|
||||
goto_out;
|
||||
|
||||
outnl(f);
|
||||
if (!_print_historical_lvs(f, vg))
|
||||
goto_out;
|
||||
|
||||
_dec_indent(f);
|
||||
if (!out_text(f, "}"))
|
||||
goto_out;
|
||||
@@ -1078,7 +936,7 @@ struct dm_config_tree *export_vg_to_config_tree(struct volume_group *vg)
|
||||
return_NULL;
|
||||
}
|
||||
|
||||
if (!(vg_cft = config_tree_from_string_without_dup_node_check(buf))) {
|
||||
if (!(vg_cft = dm_config_from_string(buf))) {
|
||||
log_error("Error parsing metadata for VG %s.", vg->name);
|
||||
dm_free(buf);
|
||||
return_NULL;
|
||||
|
@@ -453,7 +453,7 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
|
||||
"not match expected name %s.", vgname);
|
||||
|
||||
bad:
|
||||
if ((info = lvmcache_info_from_pvid(dev_area->dev->pvid, dev_area->dev, 0)) &&
|
||||
if ((info = lvmcache_info_from_pvid(dev_area->dev->pvid, 0)) &&
|
||||
!lvmcache_update_vgname_and_id(info, &vgsummary_orphan))
|
||||
stack;
|
||||
|
||||
@@ -985,8 +985,8 @@ static int _vg_write_file(struct format_instance *fid __attribute__((unused)),
|
||||
if (lvm_fclose(fp, tc->path_edit))
|
||||
return_0;
|
||||
|
||||
log_debug_metadata("Renaming %s to %s", temp_file, tc->path_edit);
|
||||
if (rename(temp_file, tc->path_edit)) {
|
||||
log_debug_metadata("Renaming %s to %s", temp_file, tc->path_edit);
|
||||
log_error("%s: rename to %s failed: %s", temp_file,
|
||||
tc->path_edit, strerror(errno));
|
||||
return 0;
|
||||
@@ -1153,6 +1153,7 @@ int vgname_from_mda(const struct format_type *fmt,
|
||||
uint32_t wrap = 0;
|
||||
unsigned int len = 0;
|
||||
char buf[NAME_LEN + 1] __attribute__((aligned(8)));
|
||||
char uuid[64] __attribute__((aligned(8)));
|
||||
uint64_t buffer_size, current_usage;
|
||||
unsigned used_cached_metadata = 0;
|
||||
|
||||
@@ -1209,7 +1210,7 @@ int vgname_from_mda(const struct format_type *fmt,
|
||||
used_cached_metadata = 1;
|
||||
|
||||
/* FIXME 64-bit */
|
||||
if (!text_vgsummary_import(fmt, dev_area->dev,
|
||||
if (!text_vgname_import(fmt, dev_area->dev,
|
||||
(off_t) (dev_area->start + rlocn->offset),
|
||||
(uint32_t) (rlocn->size - wrap),
|
||||
(off_t) (dev_area->start + MDA_HEADER_SIZE),
|
||||
@@ -1221,14 +1222,16 @@ int vgname_from_mda(const struct format_type *fmt,
|
||||
if (!validate_name(vgsummary->vgname))
|
||||
return_0;
|
||||
|
||||
if (!id_write_format((struct id *)&vgsummary->vgid, uuid, sizeof(uuid)))
|
||||
return_0;
|
||||
|
||||
log_debug_metadata("%s: %s metadata at %" PRIu64 " size %" PRIu64
|
||||
" (in area at %" PRIu64 " size %" PRIu64
|
||||
") for %s (" FMTVGID ")",
|
||||
") for %s (%s)",
|
||||
dev_name(dev_area->dev),
|
||||
used_cached_metadata ? "Using cached" : "Found",
|
||||
dev_area->start + rlocn->offset,
|
||||
rlocn->size, dev_area->start, dev_area->size, vgsummary->vgname,
|
||||
(char *)&vgsummary->vgid);
|
||||
rlocn->size, dev_area->start, dev_area->size, vgsummary->vgname, uuid);
|
||||
|
||||
if (mda_free_sectors) {
|
||||
current_usage = (rlocn->size + SECTOR_SIZE - UINT64_C(1)) -
|
||||
@@ -1447,7 +1450,7 @@ static int _text_pv_needs_rewrite(const struct format_type *fmt, struct physical
|
||||
if (!pv->is_labelled)
|
||||
return 1;
|
||||
|
||||
if (!(info = lvmcache_info_from_pvid((const char *)&pv->id, pv->dev, 0))) {
|
||||
if (!(info = lvmcache_info_from_pvid((const char *)&pv->id, 0))) {
|
||||
log_error("Failed to find cached info for PV %s.", pv_dev_name(pv));
|
||||
return 0;
|
||||
}
|
||||
@@ -1525,11 +1528,11 @@ static int _text_pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter)))
|
||||
return_0;
|
||||
|
||||
if (lvmetad_used()) {
|
||||
info = lvmcache_info_from_pvid(dev->pvid, dev, 0);
|
||||
if (lvmetad_active()) {
|
||||
info = lvmcache_info_from_pvid(dev->pvid, 0);
|
||||
if (!info && !lvmetad_pv_lookup_by_dev(fmt->cmd, dev, NULL))
|
||||
return 0;
|
||||
info = lvmcache_info_from_pvid(dev->pvid, dev, 0);
|
||||
info = lvmcache_info_from_pvid(dev->pvid, 0);
|
||||
} else {
|
||||
struct label *label;
|
||||
if (!(label_read(dev, &label, UINT64_C(0))))
|
||||
@@ -1547,11 +1550,12 @@ static int _text_pv_read(const struct format_type *fmt, const char *pv_name,
|
||||
}
|
||||
|
||||
static int _text_pv_initialise(const struct format_type *fmt,
|
||||
struct pv_create_args *pva,
|
||||
const int64_t label_sector,
|
||||
unsigned long data_alignment,
|
||||
unsigned long data_alignment_offset,
|
||||
struct pvcreate_restorable_params *rp,
|
||||
struct physical_volume *pv)
|
||||
{
|
||||
unsigned long data_alignment = pva->data_alignment;
|
||||
unsigned long data_alignment_offset = pva->data_alignment_offset;
|
||||
unsigned long adjustment, final_alignment = 0;
|
||||
|
||||
if (!data_alignment)
|
||||
@@ -1588,13 +1592,13 @@ static int _text_pv_initialise(const struct format_type *fmt,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pv->size < final_alignment + pva->ba_size) {
|
||||
if (pv->size < final_alignment + rp->ba_size) {
|
||||
log_error("%s: Bootloader area with data-aligned start must "
|
||||
"not exceed device size.", pv_dev_name(pv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pva->pe_start == PV_PE_START_CALC) {
|
||||
if (rp->pe_start == PV_PE_START_CALC) {
|
||||
/*
|
||||
* Calculate new PE start and bootloader area start value.
|
||||
* Make sure both are properly aligned!
|
||||
@@ -1604,10 +1608,10 @@ static int _text_pv_initialise(const struct format_type *fmt,
|
||||
* This needs to be done as we can't have a PV without any DA.
|
||||
* But we still want to support a PV with BA only!
|
||||
*/
|
||||
if (pva->ba_size) {
|
||||
if (rp->ba_size) {
|
||||
pv->ba_start = final_alignment;
|
||||
pv->ba_size = pva->ba_size;
|
||||
if ((adjustment = pva->ba_size % pv->pe_align))
|
||||
pv->ba_size = rp->ba_size;
|
||||
if ((adjustment = rp->ba_size % pv->pe_align))
|
||||
pv->ba_size += pv->pe_align - adjustment;
|
||||
if (pv->size < pv->ba_start + pv->ba_size)
|
||||
pv->ba_size = pv->size - pv->ba_start;
|
||||
@@ -1622,26 +1626,26 @@ static int _text_pv_initialise(const struct format_type *fmt,
|
||||
* it in between the final alignment and existing PE start
|
||||
* if possible.
|
||||
*/
|
||||
pv->pe_start = pva->pe_start;
|
||||
if (pva->ba_size) {
|
||||
if ((pva->ba_start && pva->ba_start + pva->ba_size > pva->pe_start) ||
|
||||
(pva->pe_start <= final_alignment) ||
|
||||
(pva->pe_start - final_alignment < pva->ba_size)) {
|
||||
pv->pe_start = rp->pe_start;
|
||||
if (rp->ba_size) {
|
||||
if ((rp->ba_start && rp->ba_start + rp->ba_size > rp->pe_start) ||
|
||||
(rp->pe_start <= final_alignment) ||
|
||||
(rp->pe_start - final_alignment < rp->ba_size)) {
|
||||
log_error("%s: Bootloader area would overlap "
|
||||
"data area.", pv_dev_name(pv));
|
||||
return 0;
|
||||
} else {
|
||||
pv->ba_start = pva->ba_start ? : final_alignment;
|
||||
pv->ba_size = pva->ba_size;
|
||||
pv->ba_start = rp->ba_start ? : final_alignment;
|
||||
pv->ba_size = rp->ba_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pva->extent_size)
|
||||
pv->pe_size = pva->extent_size;
|
||||
if (rp->extent_size)
|
||||
pv->pe_size = rp->extent_size;
|
||||
|
||||
if (pva->extent_count)
|
||||
pv->pe_count = pva->extent_count;
|
||||
if (rp->extent_count)
|
||||
pv->pe_count = rp->extent_count;
|
||||
|
||||
if ((pv->pe_start + pv->pe_count * (uint64_t)pv->pe_size - 1) > pv->size) {
|
||||
log_error("Physical extents end beyond end of device %s.",
|
||||
@@ -1649,8 +1653,8 @@ static int _text_pv_initialise(const struct format_type *fmt,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pva->label_sector != -1)
|
||||
pv->label_sector = pva->label_sector;
|
||||
if (label_sector != -1)
|
||||
pv->label_sector = label_sector;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -1815,7 +1819,7 @@ static int _text_pv_setup(const struct format_type *fmt,
|
||||
*/
|
||||
else {
|
||||
if (!pv->dev ||
|
||||
!(info = lvmcache_info_from_pvid(pv->dev->pvid, pv->dev, 0))) {
|
||||
!(info = lvmcache_info_from_pvid(pv->dev->pvid, 0))) {
|
||||
log_error("PV %s missing from cache", pv_dev_name(pv));
|
||||
return 0;
|
||||
}
|
||||
|
@@ -51,9 +51,9 @@ struct text_vg_version_ops {
|
||||
unsigned allow_lvmetad_extensions);
|
||||
void (*read_desc) (struct dm_pool * mem, const struct dm_config_tree *cf,
|
||||
time_t *when, char **desc);
|
||||
int (*read_vgsummary) (const struct format_type *fmt,
|
||||
const struct dm_config_tree *cft,
|
||||
struct lvmcache_vgsummary *vgsummary);
|
||||
int (*read_vgname) (const struct format_type *fmt,
|
||||
const struct dm_config_tree *cft,
|
||||
struct lvmcache_vgsummary *vgsummary);
|
||||
};
|
||||
|
||||
struct text_vg_version_ops *text_vg_vsn1_init(void);
|
||||
@@ -78,7 +78,7 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid,
|
||||
uint32_t checksum,
|
||||
time_t *when, char **desc);
|
||||
|
||||
int text_vgsummary_import(const struct format_type *fmt,
|
||||
int text_vgname_import(const struct format_type *fmt,
|
||||
struct device *dev,
|
||||
off_t offset, uint32_t size,
|
||||
off_t offset2, uint32_t size2,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user